receive AVDTP_Suspend response rejection which cause the A2DP disocnnected.
There is collision of AVDTP_Suspend request:
We send AVDTP_Suspend request and the headset send AVDTP_Suspend request also at the same time.
then We send AVDTP_Suspend response, but the headset send AVDTP_Suspend response rejection
with error code bad state after it receive the AVDTP_Suspend response from us.
we call bta_av_suspend_cfm twice in this case:
the first time we will call bta_av_suspend_cfm without error after receive AVDTP_Suspend request from headset.
the second time we will call bta_av_suspend_cfm with error bad state after receive AVDTP_Suspend response rejection from headset.
To fix this problem, we should ignore the AVDTP_Suspend response rejection from headset
after receive AVDTP_Suspend request from headset.
After we receive AVDTP_Suspend request from headset, the scb state will be changed to AVDT_SCB_OPEN_ST from AVDT_SCB_STREAM_ST.
but when we receive AVDTP_Suspend response rejection from headset, we should ignore it when we are in AVDT_SCB_OPEN_ST.
and also currently we already ignore AVDTP_Suspend response when we are in AVDT_SCB_OPEN_ST,
I don't know why we didn't do it for AVDTP Suspend rejection.
issue
8735903
Change-Id: I8db3ea6e7e4edfea41f255e7e29b8c7255cf3d96
APPL_TRACE_DEBUG2 ("bta_av_suspend_cfm:audio_open_cnt = %d, err_code = %d",
bta_av_cb.audio_open_cnt, err_code);
+ if (p_scb->started == FALSE)
+ {
+ /* handle the condition where there is a collision of SUSPEND req from either side
+ ** Second SUSPEND req could be rejected. Do not treat this as a failure
+ */
+ APPL_TRACE_WARNING1("bta_av_suspend_cfm: already suspended, ignore, err_code %d",
+ err_code);
+ return;
+ }
+
suspend_rsp.status = BTA_AV_SUCCESS;
- if (err_code)
+ if (err_code && (err_code != AVDT_ERR_BAD_STATE))
{
/* Disable suspend feature only with explicit rejection(not with timeout) */
if (err_code != AVDT_ERR_TIMEOUT)
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* MSG_START_RSP_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
-/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_HDL_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},