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

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

Merge "A2dp 1.0 control: separate command handlers"

parents c84f8971 aebf908e
Loading
Loading
Loading
Loading
+207 −190
Original line number Diff line number Diff line
@@ -62,69 +62,40 @@ void btif_a2dp_control_cleanup(void) {
  }
}

static void btif_a2dp_recv_ctrl_data(void) {
  tA2DP_CTRL_CMD cmd = A2DP_CTRL_CMD_NONE;
  int n;

  uint8_t read_cmd = 0; /* The read command size is one octet */
  n = UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, &read_cmd, 1);
  cmd = static_cast<tA2DP_CTRL_CMD>(read_cmd);

  /* detach on ctrl channel means audioflinger process was terminated */
  if (n == 0) {
    APPL_TRACE_WARNING("%s: CTRL CH DETACHED", __func__);
    UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_CTRL);
    return;
  }

  // Don't log A2DP_CTRL_GET_PRESENTATION_POSITION by default, because it
  // could be very chatty when audio is streaming.
  if (cmd == A2DP_CTRL_GET_PRESENTATION_POSITION) {
    APPL_TRACE_DEBUG("%s: a2dp-ctrl-cmd : %s", __func__,
                     audio_a2dp_hw_dump_ctrl_event(cmd));
  } else {
    APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s", __func__,
                       audio_a2dp_hw_dump_ctrl_event(cmd));
  }

  a2dp_cmd_pending = cmd;
  switch (cmd) {
    case A2DP_CTRL_CMD_CHECK_READY:
static tA2DP_CTRL_ACK btif_a2dp_control_on_check_ready() {
  if (btif_a2dp_source_media_task_is_shutting_down()) {
        APPL_TRACE_WARNING("%s: A2DP command %s while media task shutting down",
                           __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
        btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
        return;
    APPL_TRACE_WARNING(
        "%s: A2DP command check ready while media task shutting down",
        __func__);
    return A2DP_CTRL_ACK_FAILURE;
  }

  /* check whether AV is ready to setup A2DP datapath */
  if (btif_av_stream_ready() || btif_av_stream_started_ready()) {
        btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
    return A2DP_CTRL_ACK_SUCCESS;
  } else {
        APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
                           __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
        btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
    APPL_TRACE_WARNING(
        "%s: A2DP command check ready while AV stream is not ready", __func__);
    return A2DP_CTRL_ACK_FAILURE;
  }
}
      break;

    case A2DP_CTRL_CMD_START:
static tA2DP_CTRL_ACK btif_a2dp_control_on_start() {
  /*
   * Don't send START request to stack while we are in a call.
   * Some headsets such as "Sony MW600", don't allow AVDTP START
   * while in a call, and respond with BAD_STATE.
   */
  if (!bluetooth::headset::IsCallIdle()) {
        APPL_TRACE_WARNING("%s: A2DP command %s while call state is busy",
                           __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
        btif_a2dp_command_ack(A2DP_CTRL_ACK_INCALL_FAILURE);
        break;
    APPL_TRACE_WARNING("%s: A2DP command start while call state is busy",
                       __func__);
    return A2DP_CTRL_ACK_INCALL_FAILURE;
  }

  if (btif_a2dp_source_is_streaming()) {
        APPL_TRACE_WARNING("%s: A2DP command %s while source is streaming",
                           __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
        btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
        break;
    APPL_TRACE_WARNING("%s: A2DP command start while source is streaming",
                       __func__);
    return A2DP_CTRL_ACK_FAILURE;
  }

  if (btif_av_stream_ready()) {
@@ -138,9 +109,7 @@ static void btif_a2dp_recv_ctrl_data(void) {
     * procedure is completed, othewise send it now.
     */
    btif_av_stream_start();
        if (btif_av_get_peer_sep() == AVDT_TSEP_SRC)
          btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
        break;
    if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) return A2DP_CTRL_ACK_SUCCESS;
  }

  if (btif_av_stream_started_ready()) {
@@ -150,30 +119,28 @@ static void btif_a2dp_recv_ctrl_data(void) {
     */
    UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb,
              A2DP_DATA_PATH);
        btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
        break;
    return A2DP_CTRL_ACK_SUCCESS;
  }
  APPL_TRACE_WARNING("%s: A2DP command start while AV stream is not ready",
                     __func__);
  return A2DP_CTRL_ACK_FAILURE;
}
      APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
                         __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
      btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
      break;

    case A2DP_CTRL_CMD_STOP:
static tA2DP_CTRL_ACK btif_a2dp_control_on_stop() {
  if (btif_av_get_peer_sep() == AVDT_TSEP_SNK &&
      !btif_a2dp_source_is_streaming()) {
    /* We are already stopped, just ack back */
        btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
        break;
    return A2DP_CTRL_ACK_SUCCESS;
  }
  btif_av_stream_stop(RawAddress::kEmpty);
      btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
      break;
  return A2DP_CTRL_ACK_SUCCESS;
}

    case A2DP_CTRL_CMD_SUSPEND:
static void btif_a2dp_control_on_suspend() {
  /* Local suspend */
  if (btif_av_stream_started_ready()) {
    btif_av_stream_suspend();
        break;
    return;
  }
  /* If we are not in started state, just ack back ok and let
   * audioflinger close the channel. This can happen if we are
@@ -181,9 +148,9 @@ static void btif_a2dp_recv_ctrl_data(void) {
   */
  btif_av_clear_remote_suspend_flag();
  btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
      break;
}

    case A2DP_CTRL_GET_INPUT_AUDIO_CONFIG: {
static void btif_a2dp_control_on_get_input_audio_config() {
  tA2DP_SAMPLE_RATE sample_rate = btif_a2dp_sink_get_sample_rate();
  tA2DP_CHANNEL_COUNT channel_count = btif_a2dp_sink_get_channel_count();

@@ -193,10 +160,9 @@ static void btif_a2dp_recv_ctrl_data(void) {
            sizeof(tA2DP_SAMPLE_RATE));
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, &channel_count,
            sizeof(tA2DP_CHANNEL_COUNT));
      break;
}

    case A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG: {
static void btif_a2dp_control_on_get_output_audio_config() {
  btav_a2dp_codec_config_t codec_config;
  btav_a2dp_codec_config_t codec_capability;
  codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -227,18 +193,15 @@ static void btif_a2dp_recv_ctrl_data(void) {
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
            reinterpret_cast<const uint8_t*>(&codec_capability.sample_rate),
            sizeof(btav_a2dp_codec_sample_rate_t));
      UIPC_Send(
          *a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
            reinterpret_cast<const uint8_t*>(&codec_capability.bits_per_sample),
            sizeof(btav_a2dp_codec_bits_per_sample_t));
      UIPC_Send(
          *a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
            reinterpret_cast<const uint8_t*>(&codec_capability.channel_mode),
            sizeof(btav_a2dp_codec_channel_mode_t));
      break;
}

    case A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG: {
static void btif_a2dp_control_on_set_output_audio_config() {
  btav_a2dp_codec_config_t codec_config;
  codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
  codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
@@ -250,9 +213,8 @@ static void btif_a2dp_recv_ctrl_data(void) {
                reinterpret_cast<uint8_t*>(&codec_config.sample_rate),
                sizeof(btav_a2dp_codec_sample_rate_t)) !=
      sizeof(btav_a2dp_codec_sample_rate_t)) {
        APPL_TRACE_ERROR("%s: Error reading sample rate from audio HAL",
                         __func__);
        break;
    APPL_TRACE_ERROR("%s: Error reading sample rate from audio HAL", __func__);
    return;
  }
  if (UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL,
                reinterpret_cast<uint8_t*>(&codec_config.bits_per_sample),
@@ -260,15 +222,14 @@ static void btif_a2dp_recv_ctrl_data(void) {
      sizeof(btav_a2dp_codec_bits_per_sample_t)) {
    APPL_TRACE_ERROR("%s: Error reading bits per sample from audio HAL",
                     __func__);
        break;
    return;
  }
  if (UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL,
                reinterpret_cast<uint8_t*>(&codec_config.channel_mode),
                sizeof(btav_a2dp_codec_channel_mode_t)) !=
      sizeof(btav_a2dp_codec_channel_mode_t)) {
        APPL_TRACE_ERROR("%s: Error reading channel mode from audio HAL",
                         __func__);
        break;
    APPL_TRACE_ERROR("%s: Error reading channel mode from audio HAL", __func__);
    return;
  }
  APPL_TRACE_DEBUG(
      "%s: A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG: "
@@ -277,15 +238,13 @@ static void btif_a2dp_recv_ctrl_data(void) {
      __func__, codec_config.sample_rate, codec_config.bits_per_sample,
      codec_config.channel_mode);
  btif_a2dp_source_feeding_update_req(codec_config);
      break;
}

    case A2DP_CTRL_GET_PRESENTATION_POSITION: {
static void btif_a2dp_control_on_get_presentation_position() {
  btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);

  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
                (uint8_t*)&(delay_report_stats.total_bytes_read),
                sizeof(uint64_t));
            (uint8_t*)&(delay_report_stats.total_bytes_read), sizeof(uint64_t));
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
            (uint8_t*)&(delay_report_stats.audio_delay), sizeof(uint16_t));

@@ -294,10 +253,68 @@ static void btif_a2dp_recv_ctrl_data(void) {
            sizeof(seconds));

  uint32_t nsec = delay_report_stats.timestamp.tv_nsec;
      UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, (uint8_t*)&nsec,
                sizeof(nsec));
      break;
  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, (uint8_t*)&nsec, sizeof(nsec));
}

static void btif_a2dp_recv_ctrl_data(void) {
  tA2DP_CTRL_CMD cmd = A2DP_CTRL_CMD_NONE;
  int n;

  uint8_t read_cmd = 0; /* The read command size is one octet */
  n = UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, &read_cmd, 1);
  cmd = static_cast<tA2DP_CTRL_CMD>(read_cmd);

  /* detach on ctrl channel means audioflinger process was terminated */
  if (n == 0) {
    APPL_TRACE_WARNING("%s: CTRL CH DETACHED", __func__);
    UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_CTRL);
    return;
  }

  // Don't log A2DP_CTRL_GET_PRESENTATION_POSITION by default, because it
  // could be very chatty when audio is streaming.
  if (cmd == A2DP_CTRL_GET_PRESENTATION_POSITION) {
    APPL_TRACE_DEBUG("%s: a2dp-ctrl-cmd : %s", __func__,
                     audio_a2dp_hw_dump_ctrl_event(cmd));
  } else {
    APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s", __func__,
                       audio_a2dp_hw_dump_ctrl_event(cmd));
  }

  a2dp_cmd_pending = cmd;
  switch (cmd) {
    case A2DP_CTRL_CMD_CHECK_READY:
      btif_a2dp_command_ack(btif_a2dp_control_on_check_ready());
      break;

    case A2DP_CTRL_CMD_START:
      btif_a2dp_command_ack(btif_a2dp_control_on_start());
      break;

    case A2DP_CTRL_CMD_STOP:
      btif_a2dp_command_ack(btif_a2dp_control_on_stop());
      break;

    case A2DP_CTRL_CMD_SUSPEND:
      btif_a2dp_control_on_suspend();
      break;

    case A2DP_CTRL_GET_INPUT_AUDIO_CONFIG:
      btif_a2dp_control_on_get_input_audio_config();
      break;

    case A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG:
      btif_a2dp_control_on_get_output_audio_config();
      break;

    case A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG:
      btif_a2dp_control_on_set_output_audio_config();
      break;

    case A2DP_CTRL_GET_PRESENTATION_POSITION:
      btif_a2dp_control_on_get_presentation_position();
      break;

    default:
      APPL_TRACE_ERROR("%s: UNSUPPORTED CMD (%d)", __func__, cmd);
      btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);