Просмотр исходного кода

Redesign separating AVRC & A2DP

1. Add g_av_with_rc to avrc_tg_init function
2. Remove g_av_open_fail
3. Add comment in API files
4. Add a2dp init & deinit state variable to inidcate a2dp statement
weitianhua 5 лет назад
Родитель
Сommit
84cda60478

+ 4 - 2
components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h

@@ -194,7 +194,8 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
 /**
  *
  * @brief           Initialize the bluetooth A2DP sink module. This function should be called
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: A2DP can work independently.
+ *                  If you want to use AVRC together, you should initiate AVRC first.
  *
  * @return
  *                  - ESP_OK: if the initialization request is sent successfully
@@ -265,7 +266,8 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
 /**
  *
  * @brief           Initialize the bluetooth A2DP source module. This function should be called
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: A2DP can work independently.
+ *                  If you want to use AVRC together, you should initiate AVRC first.
  *
  * @return
  *                  - ESP_OK: if the initialization request is sent successfully

+ 8 - 4
components/bt/host/bluedroid/api/include/api/esp_avrc_api.h

@@ -414,7 +414,8 @@ esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback);
 /**
  *
  * @brief           Initialize the bluetooth AVRCP controller module, This function should be called
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
+ *                  AVRC should be used along with A2DP and AVRC should be initialized before A2DP.
  *
  * @return
  *                  - ESP_OK: success
@@ -427,7 +428,8 @@ esp_err_t esp_avrc_ct_init(void);
 /**
  *
  * @brief           De-initialize AVRCP controller module. This function should be called after
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
+ *                  AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP.
  *
  * @return
  *                  - ESP_OK: success
@@ -543,7 +545,8 @@ esp_err_t esp_avrc_tg_register_callback(esp_avrc_tg_cb_t callback);
 /**
  *
  * @brief           Initialize the bluetooth AVRCP target module, This function should be called
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
+ *                  AVRC should be used along with A2DP and AVRC should be initialized before A2DP.
  *
  * @return
  *                  - ESP_OK: success
@@ -556,7 +559,8 @@ esp_err_t esp_avrc_tg_init(void);
 /**
  *
  * @brief           De-initialize AVRCP target module. This function should be called after
- *                  after esp_bluedroid_enable() completes successfully
+ *                  after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
+ *                  AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP.
  *
  * @return
  *                  - ESP_OK: success

+ 58 - 75
components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c

@@ -42,8 +42,12 @@
 
 #if BTC_AV_INCLUDED
 
-bool g_av_open_fail;
+// global variable to inidcate avrc is initialized with a2dp
 bool g_av_with_rc;
+// global variable to indicate a2dp is initialized
+bool g_a2dp_on_init;
+// global variable to indicate a2dp is deinitialized
+bool g_a2dp_on_deinit;
 
 /*****************************************************************************
 **  Constants & Macros
@@ -96,14 +100,9 @@ typedef struct {
     bt_bdaddr_t target_bda;
 } btc_av_disconn_req_t;
 
-typedef struct {
-    esp_a2d_connection_state_t state;
-    btc_sm_state_t av_state;
-} btc_av_open_t;
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
-btc_av_open_t av_open;
 
 #if A2D_DYNAMIC_MEMORY == FALSE
 static btc_av_cb_t btc_av_cb = {0};
@@ -304,8 +303,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
 {
     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
-    // Init av_open struct
-    memset(&av_open, 0, sizeof(btc_av_open_t));
 
     switch (event) {
     case BTC_SM_ENTER_EVT:
@@ -314,12 +311,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
         btc_av_cb.flags = 0;
         btc_av_cb.edr = 0;
         btc_a2dp_on_idle();
-
-        if(g_av_open_fail) {
-            BTC_TRACE_ERROR("AV_OPEN: Sta %d , SM Sta %d\n",av_open.state, av_open.av_state);
-            /* inform the application of the event */
-            btc_report_connection_state(av_open.state, &(btc_av_cb.peer_bda), 0);
-        }
         break;
 
     case BTC_SM_EXIT_EVT:
@@ -330,9 +321,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
 
     case BTA_AV_REGISTER_EVT:
         btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
-        // Init av_open struct and av_open_state
-        memset(&av_open, 0, sizeof(btc_av_open_t));
-        g_av_open_fail = false;
         break;
 
     case BTA_AV_PENDING_EVT:
@@ -363,20 +351,20 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
     } break;
 
     case BTC_AV_DISCONNECT_REQ_EVT:
-        BTC_TRACE_WARNING("BTC_AV_DISCONNECT_REQ_EVT received when no link up.");
+        BTC_TRACE_WARNING("No Link At All.");
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0);
         break;
 
     case BTA_AV_RC_OPEN_EVT:
         /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
-        * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
-        * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
-        * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
-        * headsets, as some headsets initiate the AVRC connection first and then
-        * immediately initiate the AV connection
-        *
-        * TODO: We may need to do this only on an AVRCP Play. FixMe
-        */
+         * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
+         * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
+         * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
+         * headsets, as some headsets initiate the AVRC connection first and then
+         * immediately initiate the AV connection
+         *
+         * TODO: We may need to do this only on an AVRCP Play. FixMe
+         */
 #if BTC_AV_SRC_INCLUDED
         BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
         btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
@@ -407,7 +395,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
                  dump_av_sm_event_name(event));
         return FALSE;
-
     }
 
     return TRUE;
@@ -438,32 +425,34 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
         break;
 
     case BTA_AV_REJECT_EVT:
-        BTC_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT \n");
-        g_av_open_fail = true;
+        BTC_TRACE_WARNING(" Received  BTA_AV_REJECT_EVT \n");
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0);
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
 
     case BTA_AV_OPEN_EVT: {
         tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
+        esp_a2d_connection_state_t conn_stat;
+        btc_sm_state_t av_state;
         BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
                         p_bta_data->open.edr, p_bta_data->open.sep);
 
         if (p_bta_data->open.status == BTA_AV_SUCCESS) {
-            av_open.state = ESP_A2D_CONNECTION_STATE_CONNECTED;
-            av_open.av_state = BTC_AV_STATE_OPENED;
             btc_av_cb.edr = p_bta_data->open.edr;
-
             btc_av_cb.peer_sep = p_bta_data->open.sep;
+
+            conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
+            av_state = BTC_AV_STATE_OPENED;
         } else {
-            BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n",
-                     p_bta_data->open.status );
-            av_open.state = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
-            av_open.av_state  = BTC_AV_STATE_IDLE;
-            g_av_open_fail = true;
+            BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n", p_bta_data->open.status);
+            
+            conn_stat = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
+            av_state = BTC_AV_STATE_IDLE;
         }
-
+        /* inform the application of the event */
+        btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0);
         /* change state to open/idle based on the status */
-        btc_sm_change_state(btc_av_cb.sm_handle, av_open.av_state);
+        btc_sm_change_state(btc_av_cb.sm_handle, av_state);
 
         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
             /* if queued PLAY command,  send it now */
@@ -518,13 +507,11 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
             break;
         }
 
-        CHECK_RC_EVENT(event, p_data);
+    CHECK_RC_EVENT(event, p_data);
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
-
     }
     return TRUE;
 }
@@ -584,9 +571,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
     case BTA_AV_CLOSE_EVT: {
         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
         /* inform the application that we are disconnecting */
-        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
-                                    close->disc_rsn);
-        g_av_open_fail = false;
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
     }
@@ -597,14 +582,12 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
         break;
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
     }
     return TRUE;
 }
 
-
 /*****************************************************************************
 **
 ** Function     btc_av_state_opened_handler
@@ -614,7 +597,6 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
 ** Returns      TRUE if event was processed, FALSE otherwise
 **
 *******************************************************************************/
-
 static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
 {
     tBTA_AV *p_av = (tBTA_AV *)p_data;
@@ -632,8 +614,6 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
     case BTC_SM_ENTER_EVT:
         btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_STOP;
         btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
-        /* inform the application of the event */
-        btc_report_connection_state(av_open.state, &(btc_av_cb.peer_bda), 0);
         break;
 
     case BTC_SM_EXIT_EVT:
@@ -701,7 +681,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
 
     case BTC_AV_DISCONNECT_REQ_EVT:
         BTA_AvClose(btc_av_cb.bta_handle);
-        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
+        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
             BTA_AvCloseRc(btc_av_cb.bta_handle);
         }
 
@@ -716,14 +696,14 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
         /* inform the application that we are disconnected */
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
                                     close->disc_rsn);
-        g_av_open_fail = false;
-        /* change state to idle, send acknowledgement if start is pending */
-        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
 
         if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
             btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
             /* pending start flag will be cleared when exit current state */
         }
+
+        /* change state to idle, send acknowledgement if start is pending */
+        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
     }
 
@@ -750,7 +730,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
         btc_queue_advance();
         break;
 
-        CHECK_RC_EVENT(event, p_data);
+    CHECK_RC_EVENT(event, p_data);
 
     default:
         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
@@ -837,15 +817,15 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
 
         /* request avdtp to close */
         BTA_AvClose(btc_av_cb.bta_handle);
-        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
+        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
             BTA_AvCloseRc(btc_av_cb.bta_handle);
         }
 
-        /* wait in closing state until fully closed */
-        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
-
         /* inform the application that we are disconnecting */
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
+
+        /* wait in closing state until fully closed */
+        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
         break;
 
     case BTA_AV_SUSPEND_EVT:
@@ -868,10 +848,6 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
             return FALSE;
         }
 
-        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
-        /* suspend completed and state changed, clear pending status */
-        btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
         if (p_av->suspend.initiator != TRUE) {
             /* remote suspend, notify HAL and await audioflinger to
                suspend/stop stream */
@@ -886,6 +862,11 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
         } else {
             btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
         }
+
+        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
+
+        /* suspend completed and state changed, clear pending status */
+        btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
         break;
 
     case BTA_AV_STOP_EVT:
@@ -893,29 +874,25 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
         btc_a2dp_on_stopped(&p_av->suspend);
 
+        btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
+
         /* if stop was successful, change state to open */
         if (p_av->suspend.status == BTA_AV_SUCCESS) {
             btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
         }
-
-        btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
         break;
 
-    case BTA_AV_CLOSE_EVT: {
-
+    case BTA_AV_CLOSE_EVT:
         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
 
         /* avdtp link is closed */
         btc_a2dp_on_stopped(NULL);
-        g_av_open_fail = false;
-        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
-
         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
         /* inform the application that we are disconnected */
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
                                     close->disc_rsn);
+        btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
-    }
 
     CHECK_RC_EVENT(event, p_data);
 
@@ -1002,7 +979,6 @@ static void btc_av_event_free_data(btc_sm_event_t event, void *p_data)
 ** Returns          bt_status_t
 **
 *******************************************************************************/
-
 static bt_status_t btc_av_init(int service_id)
 {
 
@@ -1036,6 +1012,8 @@ static bt_status_t btc_av_init(int service_id)
             osi_free(btc_av_cb_ptr);
             btc_av_cb_ptr = NULL;
 #endif
+            g_a2dp_on_init = false;
+            g_a2dp_on_deinit = true;
             return BT_STATUS_FAIL;
         }
 
@@ -1050,7 +1028,8 @@ static bt_status_t btc_av_init(int service_id)
         }
 
         btc_a2dp_on_init();
-
+        g_a2dp_on_init = true;
+        g_a2dp_on_deinit = false;
         return BT_STATUS_SUCCESS;
     }
 
@@ -1118,6 +1097,8 @@ static void clean_up(int service_id)
     osi_free(btc_av_cb_ptr);
     btc_av_cb_ptr = NULL;
 #endif
+    g_a2dp_on_init = false;
+    g_a2dp_on_deinit = true;
 }
 
 /*******************************************************************************
@@ -1293,12 +1274,14 @@ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
          * be initiated by the app/audioflinger layers */
         if (g_av_with_rc) {
+            BTC_TRACE_WARNING("A2DP Enable with AVRC")
             BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD |
                         BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
                         BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
                         bte_av_callback);
             BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep);
         } else {
+            BTC_TRACE_WARNING("A2DP Enable without AVRC")
             BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD, bte_av_callback);
             BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, NULL, tsep);
         }

+ 30 - 6
components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c

@@ -1011,15 +1011,20 @@ static void btc_avrc_ct_init(void)
         return;
     }
 
-    // indicate that using A2DP with AVRC
-    g_av_with_rc = true;
-
     /// initialize CT-specific resources
     s_rc_ct_init = BTC_RC_CT_INIT_MAGIC;
 
     /// initialize CT-TG shared resources
     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
+
+        if (!g_av_with_rc) {
+            g_av_with_rc = true;
+        }
+
+        if (g_a2dp_on_init) {
+            BTC_TRACE_WARNING("AVRC Controller is expected to be initialized in advance of A2DP !!!");
+        }
     }
 }
 
@@ -1037,20 +1042,24 @@ static void btc_avrc_ct_deinit(void)
 {
     BTC_TRACE_API("## %s ##", __FUNCTION__);
 
+    if (g_a2dp_on_deinit) {
+        BTC_TRACE_WARNING("A2DP already deinit, AVRC CT shuold deinit in advance of A2DP !!!");
+    }
+
     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
         BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
         return;
     }
 
-    // indicate that using A2DP with AVRC
-    g_av_with_rc = true;
-
     /// deinit CT-specific resources
     s_rc_ct_init = 0;
 
     /// deinit CT-TG shared resources
     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
+        if (g_av_with_rc) {
+            g_av_with_rc = false;
+        }
     }
 
     BTC_TRACE_API("## %s ## completed", __FUNCTION__);
@@ -1285,6 +1294,14 @@ static void btc_avrc_tg_init(void)
     /// initialize CT-TG shared resources
     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
+
+        if (!g_av_with_rc) {
+            g_av_with_rc = true;
+        }
+
+        if (g_a2dp_on_init) {
+            BTC_TRACE_WARNING("AVRC Taget is expected to be initialized in advance of A2DP !!!");
+        }
     }
 
     s_rc_tg_init = BTC_RC_TG_INIT_MAGIC;
@@ -1304,6 +1321,10 @@ static void btc_avrc_tg_deinit(void)
 {
     BTC_TRACE_API("## %s ##", __FUNCTION__);
 
+    if (g_a2dp_on_deinit) {
+        BTC_TRACE_WARNING("A2DP already deinit, AVRC TG shuold deinit in advance of A2DP !!!");
+    }
+
     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
         BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
         return;
@@ -1317,6 +1338,9 @@ static void btc_avrc_tg_deinit(void)
     /// deinit CT-TG shared resources
     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
+        if (g_av_with_rc) {
+            g_av_with_rc = false;
+        }
     }
 
     BTC_TRACE_API("## %s ## completed", __FUNCTION__);

+ 6 - 1
components/bt/host/bluedroid/btc/profile/std/include/btc_av.h

@@ -33,8 +33,13 @@
 #include "bta/bta_av_api.h"
 
 #if (BTC_AV_INCLUDED == TRUE)
-extern bool g_av_open_fail;
+
+// global variable to inidcate avrc is initialized with a2dp
 extern bool g_av_with_rc;
+// global variable to indicate a2dp is initialized
+extern bool g_a2dp_on_init;
+// global variable to indicate a2dp is deinitialized
+extern bool g_a2dp_on_deinit;
 /*******************************************************************************
 **  Type definitions for callback functions
 ********************************************************************************/