/*************************************************************************** * Function handle_rc_passthrough_cmd * * - Argument: tBTA_AV_RC rc_id remote control command ID * tBTA_AV_STATE key_state status of key press * * - Description: Remote control command handler * ***************************************************************************/ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd) { const char *status; int pressed, i; /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */ if (p_remote_cmd) { /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */ if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) { if (p_remote_cmd->key_state == AVRC_STATE_PRESS) { APPL_TRACE_WARNING1("%s: AVDT not open, queuing the PLAY command", __FUNCTION__); btif_rc_cb.rc_pending_play = TRUE; } return; } if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play)) { APPL_TRACE_WARNING1("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__); btif_rc_cb.rc_pending_play = FALSE; return; } } if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) { status = "released"; pressed = 0; } else { status = "pressed"; pressed = 1; } /* If this is Play/Pause command (press or release) before processing, check the following * a voice call has ended recently * the remote device is not of type headset * If the above conditions meet, drop the Play/Pause command * This fix is to interop with certain carkits which sends an automatic PLAY or PAUSE * commands right after call ends */ if((p_remote_cmd->rc_id == BTA_AV_RC_PLAY || p_remote_cmd->rc_id == BTA_AV_RC_PAUSE)&& (btif_hf_call_terminated_recently() == TRUE) && (check_cod( (const bt_bdaddr_t*)&(btif_rc_cb.rc_addr), COD_AV_HEADSETS) != TRUE)) { BTIF_TRACE_DEBUG2("%s:Dropping the play/Pause command received right after call end cmd:%d", __FUNCTION__,p_remote_cmd->rc_id); return; } for (i = 0; key_map[i].name != NULL; i++) { if (p_remote_cmd->rc_id == key_map[i].avrcp) { BTIF_TRACE_DEBUG3("%s: %s %s", __FUNCTION__, key_map[i].name, status); /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE * comes 1 second after the press, the MediaPlayer UI goes into a bad state. * The reason for the delay could be sniff mode exit or some AVDTP procedure etc. * The fix is to generate a release right after the press and drown the 'actual' * release. */ if ((key_map[i].release_quirk == 1) && (pressed == 0)) { BTIF_TRACE_DEBUG2("%s: AVRC %s Release Faked earlier, drowned now", __FUNCTION__, key_map[i].name); return; } send_key(uinput_fd, key_map[i].mapped_id, pressed); if ((key_map[i].release_quirk == 1) && (pressed == 1)) { GKI_delay(30); // 30ms BTIF_TRACE_DEBUG2("%s: AVRC %s Release quirk enabled, send release now", __FUNCTION__, key_map[i].name); send_key(uinput_fd, key_map[i].mapped_id, 0); } break; } } if (key_map[i].name == NULL) BTIF_TRACE_ERROR3("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__, p_remote_cmd->rc_id, status); }
/*************************************************************************** * Function handle_rc_passthrough_cmd * * - Argument: tBTA_AV_RC rc_id remote control command ID * tBTA_AV_STATE key_state status of key press * * - Description: Remote control command handler * ***************************************************************************/ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd) { const char *status; int pressed, i; /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */ if (p_remote_cmd) { /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */ if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) { if (p_remote_cmd->key_state == AVRC_STATE_PRESS) { APPL_TRACE_WARNING1("%s: AVDT not open, queuing the PLAY command", __FUNCTION__); btif_rc_cb.rc_pending_play = TRUE; } return; } if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play)) { APPL_TRACE_WARNING1("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__); btif_rc_cb.rc_pending_play = FALSE; return; } } if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) { status = "released"; pressed = 0; } else { status = "pressed"; pressed = 1; } for (i = 0; key_map[i].name != NULL; i++) { if (p_remote_cmd->rc_id == key_map[i].avrcp) { BTIF_TRACE_DEBUG3("%s: %s %s", __FUNCTION__, key_map[i].name, status); /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE * comes 1 second after the press, the MediaPlayer UI goes into a bad state. * The reason for the delay could be sniff mode exit or some AVDTP procedure etc. * The fix is to generate a release right after the press and drown the 'actual' * release. */ if ((key_map[i].release_quirk == 1) && (pressed == 0)) { BTIF_TRACE_DEBUG2("%s: AVRC %s Release Faked earlier, drowned now", __FUNCTION__, key_map[i].name); return; } send_key(uinput_fd, key_map[i].mapped_id, pressed); if ((key_map[i].release_quirk == 1) && (pressed == 1)) { GKI_delay(30); // 30ms BTIF_TRACE_DEBUG2("%s: AVRC %s Release quirk enabled, send release now", __FUNCTION__, key_map[i].name); send_key(uinput_fd, key_map[i].mapped_id, 0); } break; } } if (key_map[i].name == NULL) BTIF_TRACE_ERROR3("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__, p_remote_cmd->rc_id, status); }