--- /dev/null
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021. All rights reserved.
+ * Description: This module include test function of BT HFP Service module.
+ */
+
+#include "PhoneAGService.h"
+#include <soc_osal.h>
+#include <td_base.h>
+#include <stdlib.h>
+#include "securec.h"
+#include "errcode.h"
+#include "bts_br_gap.h"
+#include "bts_hfp_ag.h"
+// #include "sample_common.h"
+#ifdef MEMORY_MINI
+#include "audio_manager.h"
+#else
+// #include "sdk_private.h"
+// /home/hcj/FD230/code/sdk/protocol/bt/host/bt/bts/brandy_service/bt_audio_wrapper/bt_audio_manager_wrapper.h
+#include "bt_audio_manager_wrapper.h"
+#endif
+
+#include "wearable_log.h"
+#include "common_def.h"
+#include "PhoneAudio.h"
+#include "cat1_ctl.h"
+#include "BluetoothHeadsetEvent.h"
+
+#include "PhoneServiceC.h"
+#include "notification_manager.h"
+
+#include "PhoneService.h"
+#include "CallerLogModel.h"
+#include "custom_utils.h"
+
+
+#define SAMPLE_HFP_TASK_STACK_SIZE 0x1600
+#define SAMPLE_HFP_TASK_PRI 20
+#define HFP_MEDIA_STATUS_DEINIT 0
+#define HFP_MEDIA_STATUS_INIT 1
+#define HFP_MEDIA_STATUS_START 2
+#define HFP_MEDIA_FLAG_IDLE 0
+#define HFP_MEDIA_FLAG_BUSY 1
+
+#define HFP_AG_IND_SIGNAL_DEFAULT 3
+#define HFP_AG_IND_BATTERY_DEFAULT 5
+
+typedef enum {
+ SAMPLE_HFP_AG_CMD_INIT = 0, /* AG初始化 */
+ SAMPLE_HFP_AG_CMD_DEINIT, /* AG去初始化 */
+ SAMPLE_HFP_AG_CMD_REG_CALLBACK, /* 注册回调 */
+ SAMPLE_HFP_AG_CMD_CONN_HFP, /* HFP连接 */
+ SAMPLE_HFP_AG_CMD_DISCONN_HFP, /* HFP断开连接 */
+ SAMPLE_HFP_AG_CMD_CONN_SCO = 5, /* 建立SCO连接 */
+ SAMPLE_HFP_AG_CMD_DISCONN_SCO, /* 断开SCO连接 */
+ SAMPLE_HFP_AG_CMD_GET_DEV_CONN_STATE, /* 获取设备Profile连接状态 */
+ SAMPLE_HFP_AG_CMD_GET_SCO_CONN_STATE, /* 获取SCO连接状态 */
+ SAMPLE_HFP_AG_CMD_ANSWER_CALL, /* 接听电话 */
+ SAMPLE_HFP_AG_CMD_FINISH_CALL = 10, /* 挂断电话 */
+ SAMPLE_HFP_AG_CMD_SET_VOLUME, /* 设置扬声器/麦克风音量 */
+ SAMPLE_HFP_AG_CMD_SEND_INCOMING_EVENT, /* 发送来电事件 */
+ SAMPLE_HFP_AG_CMD_SEND_NETWORK_EVENT, /* 发送网络事件 */
+ SAMPLE_HFP_AG_CMD_SEND_CALL_LIST, /* 发送通话列表 */
+ SAMPLE_HFP_AG_CMD_SEND_SUBSCRIBER_NUMBER = 15, /* 发送订阅号码信息 */
+ SAMPLE_HFP_AG_CMD_SEND_BATTERY_CHARGE, /* 发送电量信息 */
+ SAMPLE_HFP_AG_CMD_SEND_CMEE_ERROR, /* 发送扩展错误码信息 */
+ SAMPLE_HFP_AG_CMD_SEND_NETWORK_OPERATOR, /* 发送运营商信息 */
+ SAMPLE_HFP_AG_CMD_SEND_INDICATOR_VAL, /* 发送指示器值 */
+ SAMPLE_HFP_AG_CMD_ORIGINATE_CALL, /* 呼出电话 */
+} sample_hfp_ag_cmd_id;
+
+typedef void (*hfp_ag_sample_cmd_handle_func)(const char **params, int32_t params_cnt);
+
+typedef struct {
+ sample_hfp_ag_cmd_id id;
+ hfp_ag_sample_cmd_handle_func func;
+} sample_hfp_ag_hdl_info;
+
+static hfp_cind_info_t g_sample_hfp_cind_info = {0};
+
+
+static const bd_addr_t AG_bd_addr={0};
+
+
+static void sample_hfp_ag_print_addr(const bd_addr_t *bd_addr)
+{
+ if (bd_addr != NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"addr: %02x:%02x:**:**:**:%02x ",
+ bd_addr->addr[5], bd_addr->addr[4], bd_addr->addr[0]); /* addr 只打印0,4,5位 */
+ }
+}
+
+static int32_t g_hfp_media_status = 0;
+static int32_t g_hfp_media_flag = 0;
+
+
+static AudioCodecFormat g_hfp_codec = mSBC;
+static int32_t g_hdl_up_mic = -1;
+static int32_t g_hdl_up_sco = -1;
+static int32_t g_hdl_dn_spk = -1;
+static int32_t g_hdl_dn_sco = -1;
+static int32_t g_hdl_up_modem = -1;
+static int32_t g_hdl_dn_modem = -1;
+
+
+#ifndef MEMORY_MINI
+static int32_t audio_stream_init(void)
+{
+ /* 请求音频焦点 */
+ /* deactive响铃时申请的焦点后,重新申请通话焦点 */
+ audio_manager_activate_interrupt(AUDIO_STREAM_VOICE_CALL_VOLTE);
+ audio_manager_set_device_connection_state(IN_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED);
+ audio_manager_set_device_connection_state(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED);
+ audio_manager_set_device_connection_state(IN_MODEM_HEADSET, AUDIO_DEVICE_CONNECTED);
+ audio_manager_set_device_connection_state(OUT_MODEM_HEADSET, AUDIO_DEVICE_CONNECTED);
+
+ g_hdl_up_sco = audio_stream_in_init(AUDIO_UP_LINK, PCM);
+ g_hdl_up_modem = audio_stream_out_init(AUDIO_UP_LINK, PCM);
+
+ g_hdl_dn_sco = audio_stream_out_init(AUDIO_DOWN_LINK, mSBC);
+ g_hdl_dn_modem = audio_stream_in_init(AUDIO_DOWN_LINK, mSBC);
+
+ return 0;
+}
+
+static int32_t establish_audio_stream_pipeline(void)
+{
+ uint32_t modem_out_shm_id = 0;
+ uint32_t modem_in_shm_id = 0;
+
+ audio_stream_in_start(g_hdl_dn_modem);
+ audio_stream_out_start(g_hdl_dn_sco);
+ audio_stream_in_get_channel_id(g_hdl_dn_modem, &modem_in_shm_id);
+ audio_stream_out_attach_frontend(g_hdl_dn_sco, modem_in_shm_id);
+ audio_stream_in_start(g_hdl_up_sco);
+ audio_stream_out_start(g_hdl_up_modem);
+ audio_stream_out_get_channel_id(g_hdl_up_modem, &modem_out_shm_id);
+ audio_stream_in_attach_backend(g_hdl_up_sco, modem_out_shm_id);
+
+ return 0;
+}
+
+static int32_t abrogation_audio_stream_pipeline(void)
+{
+ /* 销毁上下行通路 */
+ audio_stream_in_stop(g_hdl_up_sco);
+ audio_stream_in_deinit(g_hdl_up_sco);
+ audio_stream_out_stop(g_hdl_up_modem);
+ audio_stream_out_deinit(g_hdl_up_modem);
+ audio_stream_out_stop(g_hdl_dn_sco);
+ audio_stream_out_deinit(g_hdl_dn_sco);
+ audio_stream_in_stop(g_hdl_dn_modem);
+ audio_stream_in_deinit(g_hdl_dn_modem);
+ audio_manager_set_device_connection_state(IN_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED);
+ audio_manager_set_device_connection_state(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED);
+ audio_manager_set_device_connection_state(IN_MODEM_HEADSET, AUDIO_DEVICE_DISCONNECTED);
+ audio_manager_set_device_connection_state(OUT_MODEM_HEADSET, AUDIO_DEVICE_DISCONNECTED);
+ /* 释放音频焦点 */
+ audio_manager_deactivate_interrupt();
+ audio_manager_deinit();
+
+ return 0;
+}
+#endif
+
+
+
+
+static int32_t sample_audio_init_start_task_body(const void *data)
+{
+ // Sample_audio_init();
+
+ // return 0;
+
+ unused(data);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample_audio_init_start enter\n");
+ while ((g_hfp_media_flag != HFP_MEDIA_FLAG_IDLE) || (g_hfp_media_status != HFP_MEDIA_STATUS_DEINIT)) {
+ osal_msleep(1);
+ }
+ /* 设置媒体状态繁忙 */
+ g_hfp_media_flag = HFP_MEDIA_FLAG_BUSY;
+ int ret;
+ audio_stream_init();
+
+ /* Init success */
+ g_hfp_media_status = HFP_MEDIA_STATUS_INIT;
+
+ /* 建立电话上下行通路 */
+ establish_audio_stream_pipeline();
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample_audio_init_start end\n");
+ /* Start success */
+ g_hfp_media_status = HFP_MEDIA_STATUS_START;
+ g_hfp_media_flag = HFP_MEDIA_FLAG_IDLE;
+ return 0;
+}
+
+static int32_t sample_audio_deinit_task_body(const void *data)
+{
+ unused(data);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample_audio_deinit enter\n");
+ while ((g_hfp_media_flag != HFP_MEDIA_FLAG_IDLE) || (g_hfp_media_status != HFP_MEDIA_STATUS_START)) {
+ osal_msleep(1);
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample_audio_deinit start\n");
+ /* 设置媒体状态繁忙 */
+ g_hfp_media_flag = HFP_MEDIA_FLAG_BUSY;
+ abrogation_audio_stream_pipeline();
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample_audio_deinit end\n");
+ /* Deinit success */
+ g_hfp_media_status = HFP_MEDIA_STATUS_DEINIT;
+ g_hfp_media_flag = HFP_MEDIA_FLAG_IDLE;
+ return 0;
+}
+
+static void sample_hfp_ag_set_spk_volume(uint8_t volume)
+{
+
+ /* vol range [0, 100] */
+ int32_t vol = volume * SAMPLE_HFP_MEDIA_VOL_LEVEL / SAMPLE_HFP_PROF_VOL_LEVEL;
+ audio_manager_set_volume(AUDIO_STREAM_VOICE_CALL_VOLTE, vol);
+
+}
+
+
+static void sample_hfp_ag_conn_state_changed_callback(const bd_addr_t *bd_addr, profile_connect_state_t state)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"state: %d\n", state);
+ //如果触发连接为电话状态,自动切到电话
+ if(state==PROFILE_STATE_CONNECTED)
+ {
+ if(OHOS::CallerLogModel::GetInstance()->GetCallSource() == OHOS::CallerLogModel::CallSourceCat1
+ && OHOS::NotificationManager::GetInstance()->GetWatchCallStatus())
+ {
+ cat1_connect_sco_();
+ }
+ else
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"电话结束\n");
+ }
+ }
+
+ if(state==PROFILE_STATE_DISCONNECTED)
+ {
+ // if(OHOS::CallerLogModel::GetInstance()->GetCallSource() == OHOS::CallerLogModel::CallSourceCat1
+ // && OHOS::NotificationManager::GetInstance()->GetWatchCallStatus())
+ // {
+ // if(volte_voice_state()==0)
+
+ // }
+ // else
+ // {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"电话结束\n");
+ // }
+ }
+
+}
+
+
+void cat1_start_SCO_audio_(void)
+{
+ uapi_cat1_start_SCO_volte_voice();
+}
+
+static void sample_hfp_ag_sco_conn_state_changed_callback(const bd_addr_t *bd_addr, hfp_sco_connect_state_t state)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"state: %d\n", state);
+ osal_kthread_handler task_body = NULL;
+ switch (state) {
+ case HFP_SCO_STATE_CONNECTING:
+ break;
+
+ case HFP_SCO_STATE_CONNECTED:
+ if(volte_voice_state()==0)
+ {
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT_HFP_SCO_AUDIO_START, nullptr, 0);
+ }
+ else
+ {
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT1_AUDIO_STOP, nullptr, 0);
+
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT_HFP_SCO_AUDIO_START, nullptr, 0);
+ }
+ Call_headset_state_updata(1);
+
+
+ break;
+
+ case HFP_SCO_STATE_DISCONNECTING:
+ break;
+ case HFP_SCO_STATE_DISCONNECTED:
+
+ if(OHOS::CallerLogModel::GetInstance()->GetCallSource() == OHOS::CallerLogModel::CallSourceCat1
+ && OHOS::NotificationManager::GetInstance()->GetWatchCallStatus())
+ {
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT1_AUDIO_STOP, nullptr, 0);
+
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT1_AUDIO_START, nullptr, 0);
+ }
+ else
+ {
+ do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_CAT1_AUDIO_STOP, nullptr, 0);
+ }
+
+ Call_headset_state_updata(0);
+ break;
+
+ default: {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"invalid state!\n");
+ break;
+ }
+ }
+}
+
+static void sample_hfp_ag_codec_changed_callback(const bd_addr_t *bd_addr, hfp_ag_codec_id_t codec)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"codec : %d\n", codec);
+
+}
+
+static void sample_hfp_ag_volume_changed_callback(const bd_addr_t *bd_addr, hfp_volume_type_t type, uint8_t volume)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"type: %d, volume: %u\n", type, volume);
+ if (type == HFP_VOLUME_SPEAKER) {
+ sample_hfp_ag_set_spk_volume(volume);
+ }
+}
+
+static void sample_hfp_ag_dial_req_callback(const bd_addr_t *bd_addr, unsigned char *number, unsigned int len)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ for (unsigned int i = 0; i < len; i++) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number: %d ", *((uint8_t *)number + i));
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"len: %d.\n", len);
+}
+
+static void sample_hfp_ag_mem_dial_req_callback(const bd_addr_t *bd_addr, unsigned int index)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"index: %d.\n", index);
+}
+
+static void sample_hfp_ag_lastnum_dial_req_callback(const bd_addr_t *bd_addr)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+}
+
+static void sample_hfp_ag_answer_call_req_callback(const bd_addr_t *bd_addr, hfp_ag_type_t type)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"type: %d.\n", type);
+}
+
+static void sample_hfp_ag_cancel_call_req_callback(const bd_addr_t *bd_addr, hfp_ag_type_t type)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"type: %d.\n", type);
+}
+
+static void sample_hfp_ag_dtmf_req_callback(const bd_addr_t *bd_addr, unsigned int code)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"code: 0x%x.\n", code);
+}
+
+static void sample_hfp_ag_subscriber_number_req_callback(const bd_addr_t *bd_addr)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ /* TODO 造数据响应 */
+}
+
+static void sample_hfp_ag_current_calls_req_callback(const bd_addr_t *bd_addr)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ /* TODO 造数据响应 */
+}
+
+static void sample_hfp_ag_current_indicator_req_callback(const bd_addr_t *bd_addr)
+{
+ g_sample_hfp_cind_info.service = 1;
+ g_sample_hfp_cind_info.call = 0;
+ g_sample_hfp_cind_info.callsetup = 0;
+ g_sample_hfp_cind_info.callheld = 0;
+ g_sample_hfp_cind_info.signal = HFP_AG_IND_SIGNAL_DEFAULT;
+ g_sample_hfp_cind_info.roam = 0;
+ g_sample_hfp_cind_info.battchg = HFP_AG_IND_BATTERY_DEFAULT;
+ errcode_t ret = (errcode_t)hfp_ag_send_indicator_val(bd_addr, &g_sample_hfp_cind_info);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag send cur indicator cbk ret=0x%x\n", ret);
+}
+
+static void sample_hfp_ag_network_operator_format_req_callback(const bd_addr_t *bd_addr)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag AT+COPS= req cbk.\n");
+}
+
+static void sample_hfp_ag_network_operator_req_callback(const bd_addr_t *bd_addr)
+{
+ sample_hfp_ag_print_addr(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag AT+COPS? req cbk.\n");
+}
+
+static void sample_hfp_ag_init(const char **params, int32_t params_cnt)
+{
+ unused(params);
+ unused(params_cnt);
+ // hfp_ag_service_init();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag init done.\n");
+}
+
+static void sample_hfp_ag_deinit(const char **params, int32_t params_cnt)
+{
+ unused(params);
+ unused(params_cnt);
+ // hfp_ag_service_deinit();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag deinit done.\n");
+}
+
+void hfp_ag_reg_callback(void)
+{
+
+ errcode_t ret = ERRCODE_BT_SUCCESS;
+ hfp_ag_callbacks_t callbacks = {
+ sample_hfp_ag_conn_state_changed_callback,
+ sample_hfp_ag_sco_conn_state_changed_callback,
+ sample_hfp_ag_codec_changed_callback,
+ sample_hfp_ag_volume_changed_callback,
+ sample_hfp_ag_dial_req_callback,
+ sample_hfp_ag_mem_dial_req_callback,
+ sample_hfp_ag_lastnum_dial_req_callback,
+ sample_hfp_ag_answer_call_req_callback,
+ sample_hfp_ag_cancel_call_req_callback,
+ sample_hfp_ag_dtmf_req_callback,
+ sample_hfp_ag_subscriber_number_req_callback,
+ sample_hfp_ag_current_calls_req_callback,
+ sample_hfp_ag_current_indicator_req_callback,
+ sample_hfp_ag_network_operator_format_req_callback,
+ sample_hfp_ag_network_operator_req_callback,
+ };
+ ret = (errcode_t)hfp_ag_register_callbacks(&callbacks);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag reg cbk ret=0x%x\n", ret);
+}
+
+/* <addr> */
+errcode_t hfp_ag_cmd_conn_hfp(const bd_addr_t *bd_addr)
+{
+ errcode_t ret = (errcode_t)hfp_ag_connect(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+ return ret;
+}
+
+/* <addr> */
+errcode_t hfp_ag_cmd_disconn_hfp(const bd_addr_t *bd_addr)
+{
+
+ errcode_t ret = (errcode_t)hfp_ag_disconnect(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+ return ret;
+}
+
+/* <addr> */
+void hfp_ag_cmd_conn_sco(const bd_addr_t *bd_addr )
+{
+
+ errcode_t ret = (errcode_t)hfp_ag_audio_connect(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u %02X %02X %02X %02X %02X %02X\n", ret,bd_addr->addr[5]
+ ,bd_addr->addr[4],bd_addr->addr[3],bd_addr->addr[2],bd_addr->addr[1],bd_addr->addr[0]);
+}
+
+/* <addr> */
+void hfp_ag_cmd_disconn_sco(const bd_addr_t *bd_addr )
+{
+ errcode_t ret = (errcode_t)hfp_ag_audio_disconnect(bd_addr);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> */
+static void sample_hfp_ag_cmd_get_dev_conn_state(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 1) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag dev conn state param is invalid.\n");
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag dev conn state decode addr error!\n");
+ // return;
+ // }
+ // int ret = hfp_ag_get_device_connect_state(&bd_addr);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %d\n", ret);
+}
+
+/* <addr> */
+static void sample_hfp_ag_cmd_get_sco_conn_state(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 1) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag sco state param is invalid.\n");
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag sco state decode addr error!\n");
+ // return;
+ // }
+ // int ret = hfp_ag_get_sco_connect_state(&bd_addr);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %d\n", ret);
+}
+
+/* <addr> */
+static void sample_hfp_ag_cmd_answer_call(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 1) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag answer call param is invalid.\n");
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag answer call decode addr error!\n");
+ // return;
+ // }
+ // errcode_t ret = (errcode_t)hfp_ag_send_answer_call_event(&bd_addr);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %d\n", ret);
+}
+
+/* <addr> <type> */
+static void sample_hfp_ag_cmd_finish_call(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 2) { /* 2: param count */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag finish call param is invalid.\n");
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag finish call decode addr error!\n");
+ // return;
+ // }
+ // hfp_ag_action_t type = (hfp_ag_action_t)atoi(params[1]);
+ // errcode_t ret = (errcode_t)hfp_ag_send_finish_call_event(&bd_addr, type);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"type: %d ret: %d\n", type, ret);
+}
+
+/* <addr> <volume_type> <volume> */
+static void sample_hfp_ag_cmd_set_volume(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 3) { /* 3个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag set volume decode addr error!\n");
+ // return;
+ // }
+ // hfp_volume_type_t type = (hfp_volume_type_t)atoi(params[1]); /* 第1个参数 */
+ // uint8_t volume = (uint8_t)atoi(params[2]); /* 第2个参数 */
+ // errcode_t ret = (errcode_t)hfp_ag_set_volume(&bd_addr, type, volume);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"type: %d volume: %u ret: %u\n", type, volume, ret);
+}
+
+/* <addr> <event> <param> */
+static void sample_hfp_ag_cmd_send_network_event(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 3) { /* 3个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag set volume decode addr error!\n");
+ // return;
+ // }
+ // hfp_ag_network_event_t event = (hfp_ag_network_event_t)atoi(params[1]); /* 第1个参数 */
+ // uint8_t param = (uint8_t)atoi(params[2]); /* 第2个参数 */
+ // errcode_t ret = (errcode_t)hfp_ag_send_network_event(&bd_addr, event, param);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"event: %d param: %u ret: %u\n", event, param, ret);
+}
+
+/* <addr> <type> <service> <number> <alpha_str> */
+static void sample_hfp_ag_cmd_send_incoming_event(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 5) { /* 5个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag set volume decode addr error!\n");
+ // return;
+ // }
+
+ // uint8_t type = (uint8_t)atoi(params[1]); /* index:1 */
+ // uint8_t service = (uint8_t)atoi(params[2]); /* index:2 */
+ // char *number_str = params[3]; /* index:3 */
+ // size_t str_len = strlen(number_str);
+ // if (str_len > HFP_AG_PHONENUM_MAX_DIGITS) { /* number最大长度为32 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number len exceeds max limit! str_len = %u \n", str_len);
+ // return;
+ // }
+ // uint8_t number_len = (uint8_t)str_len;
+
+ // char *name_str = params[4]; /* index:4 *//* index:4 */
+ // size_t name_str_len = strlen(name_str);
+ // if (name_str_len > 256) { /* name最大长度为256 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"name len exceeds max limit! str_len = %u \n", str_len);
+ // return;
+ // }
+ // uint8_t name_len = (uint8_t)name_str_len;
+
+ // hfp_phone_info_t *info = bt_os_new(sizeof(hfp_phone_info_t) + name_len);
+ // if (memset_s(info, sizeof(hfp_phone_info_t) + name_len, 0,
+ // sizeof(hfp_phone_info_t) + name_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->type = type;
+ // info->service = service;
+ // info->num_len = number_len;
+ // if (memcpy_s(info->number, HFP_AG_PHONENUM_MAX_DIGITS, (uint8_t *)number_str, str_len) != EOK) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number memcpy error.\n");
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->name_len = name_len;
+ // if (memcpy_s(info->alpha_str, name_len, (int8_t *)name_str, name_len) != EOK) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"name memcpy error.\n");
+ // bt_os_free(info);
+ // return;
+ // }
+ // errcode_t ret = (errcode_t)hfp_ag_send_network_incoming_event(&bd_addr, info);
+ // bt_os_free(info);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> <idx> <dir> <status> <mode> <mpty> <type> <number> <is_last> */
+static void sample_hfp_ag_cmd_send_call_list(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 9) { /* 9个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag set volume decode addr error!\n");
+ // return;
+ // }
+ // uint8_t number_len = 0;
+ // char *number_str = params[7]; /* 7:idx */
+ // size_t str_len = strlen(number_str);
+ // if (str_len > HFP_AG_PHONENUM_MAX_DIGITS) { /* number最大长度为32 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number len exceeds max limit! str_len = %u \n", str_len);
+ // return;
+ // }
+ // number_len = (uint8_t)str_len;
+ // hfp_clcc_info_t *info = bt_os_new(sizeof(hfp_clcc_info_t) + number_len);
+ // if (memset_s(info, sizeof(hfp_clcc_info_t) + number_len, 0,
+ // sizeof(hfp_clcc_info_t) + number_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->idx = (uint8_t)atoi(params[1]);
+ // info->dir = (uint8_t)atoi(params[2]); /* 2:idx */
+ // info->status = (uint8_t)atoi(params[3]); /* 3:idx */
+ // info->mode = (uint8_t)atoi(params[4]); /* 4:idx */
+ // info->mpty = (uint8_t)atoi(params[5]); /* 5:idx */
+ // info->type = (uint8_t)atoi(params[6]); /* 6:idx */
+ // info->num_len = number_len;
+ // if (memcpy_s(info->number, number_len, (uint8_t *)number_str, str_len) != EOK) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number memcpy error.\n");
+ // bt_os_free(info);
+ // return;
+ // }
+
+ // hfp_ag_last_t is_last = (hfp_ag_last_t)atoi(params[8]); /* 8:idx */
+ // errcode_t ret = (errcode_t)hfp_ag_send_current_calls(&bd_addr, info, is_last);
+ // bt_os_free(info);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> <type> <service> <number> <alpha_str> <is_last> */
+static void sample_hfp_ag_cmd_send_subscriber_number(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 6) { /* 6个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag set volume decode addr error!\n");
+ // return;
+ // }
+
+ // uint8_t type = (uint8_t)atoi(params[1]); /* index:1 */
+ // uint8_t service = (uint8_t)atoi(params[2]); /* index:2 */
+ // char *number_str = params[3]; /* index:3 */
+ // size_t str_len = strlen(number_str);
+ // if (str_len > 32) { /* number最大长度为32 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"number len exceeds max limit! str_len = %u \n", str_len);
+ // return;
+ // }
+ // uint8_t number_len = (uint8_t)str_len;
+
+ // char *name_str = params[4]; /* index:4 *//* index:4 */
+ // size_t name_str_len = strlen(name_str);
+ // if (name_str_len > 256) { /* name最大长度为256 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"name len exceeds max limit! str_len = %u \n", str_len);
+ // return;
+ // }
+ // uint8_t name_len = (uint8_t)name_str_len;
+
+ // hfp_phone_info_t *info = bt_os_new(sizeof(hfp_phone_info_t) + name_len);
+ // if (memset_s(info, sizeof(hfp_phone_info_t) + name_len, 0,
+ // sizeof(hfp_phone_info_t) + name_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->type = type;
+ // info->service = service;
+ // info->num_len = number_len;
+ // if (memcpy_s(info->number, HFP_AG_PHONENUM_MAX_DIGITS, (uint8_t *)number_str, str_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->name_len = name_len;
+ // if (memcpy_s(info->alpha_str, name_len, (int8_t *)name_str, name_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // hfp_ag_last_t is_last = (hfp_ag_last_t)atoi(params[5]);
+ // errcode_t ret = (errcode_t)hfp_ag_send_subscriber_number(&bd_addr, info, is_last);
+ // bt_os_free(info);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> <value> */
+static void sample_hfp_ag_cmd_send_battery_charge(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 2) { /* 2个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag send battery charge decode addr error!\n");
+ // return;
+ // }
+ // uint8_t value = (uint8_t)atoi(params[1]); /* 第1个参数 */
+ // errcode_t ret = (errcode_t)hfp_ag_send_battery_charge(&bd_addr, value);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"value: %d ret: %u\n", value, ret);
+}
+
+/* <addr> <error_code> */
+static void sample_hfp_ag_cmd_send_cmee_error(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 2) { /* 2个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag send cmee error decode addr error!\n");
+ // return;
+ // }
+ // hfp_ag_cmee_error_t error_code = (hfp_ag_cmee_error_t)atoi(params[1]); /* 第1个参数 */
+ // errcode_t ret = (errcode_t)hfp_ag_send_cmee_error(&bd_addr, error_code);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"error_code: %d ret: %u\n", error_code, ret);
+}
+
+/* <addr> <mode> <format> <operator_name> */
+static void sample_hfp_ag_cmd_send_network_operator(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 4) { /* 4个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag send network operator decode addr error!\n");
+ // return;
+ // }
+
+ // char *operator_name = params[3]; /* index3 */
+ // uint8_t operator_len = 0;
+ // size_t name_str_len = strlen(operator_name);
+ // if (name_str_len > HFP_AG_COPS_OPERATOR_MAXLEN) { /* name最大长度为16 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"name len exceeds max limit! str_len = %u \n", name_str_len);
+ // return;
+ // }
+ // operator_len = (uint8_t)name_str_len;
+
+ // hfp_cops_info_t *info = bt_os_new(sizeof(hfp_cops_info_t) + operator_len);
+ // if (memset_s(info, sizeof(hfp_cops_info_t) + operator_len, 0,
+ // sizeof(hfp_cops_info_t) + operator_len) != EOK) {
+ // bt_os_free(info);
+ // return;
+ // }
+ // info->mode = (uint8_t)atoi(params[1]);
+ // info->format = (uint8_t)atoi(params[2]); /* index2 */
+ // info->operator_len = operator_len;
+ // if (memcpy_s(info->operator_name, operator_len, (int8_t *)operator_name, operator_len) != EOK) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"name memcpy error.\n");
+ // bt_os_free(info);
+ // return;
+ // }
+
+ // errcode_t ret = (errcode_t)hfp_ag_send_network_operator(&bd_addr, info);
+ // bt_os_free(info);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> <service> <call> <callsetup> <callheld> <signal> <roam> <battchg> */
+static void sample_hfp_ag_cmd_send_indicator_val(const char **params, int32_t params_cnt)
+{
+ // if (params_cnt != 8) { /* 8个参数 */
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"params cnt err: %d!\n", params_cnt);
+ // return;
+ // }
+ // bd_addr_t bd_addr;
+ // if (decode_bd_addr_from_str(params[0], bd_addr.addr, BD_ADDR_LEN) != EXT_ERR_SUCCESS) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"sample hfp ag send indicator val decode addr error!\n");
+ // return;
+ // }
+
+ // g_sample_hfp_cind_info.service = (uint8_t)atoi(params[1]);
+ // g_sample_hfp_cind_info.call = (uint8_t)atoi(params[2]); /* index:2 */
+ // g_sample_hfp_cind_info.callsetup = (uint8_t)atoi(params[3]); /* index:3 */
+ // g_sample_hfp_cind_info.callheld = (uint8_t)atoi(params[4]); /* index:4 */
+ // g_sample_hfp_cind_info.signal = (uint8_t)atoi(params[5]); /* index:5 */
+ // g_sample_hfp_cind_info.roam = (uint8_t)atoi(params[6]); /* index:6 */
+ // g_sample_hfp_cind_info.battchg = (uint8_t)atoi(params[7]); /* index:7 */
+
+ // errcode_t ret = (errcode_t)hfp_ag_send_indicator_val(&bd_addr, &g_sample_hfp_cind_info);
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret: %u\n", ret);
+}
+
+/* <addr> */
+
+
+bool headset_Is_connect(void)
+{
+ int state = hfp_ag_get_device_connect_state(BtAvrcpSrvGetActiveAddr());
+ if(state==PROFILE_STATE_CONNECTED)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool headset_SCO_Is_connect(void)
+{
+ int state = hfp_ag_get_sco_connect_state(BtAvrcpSrvGetActiveAddr());
+ if(state==PROFILE_STATE_CONNECTED)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+
+void cat1_connect_sco_(void)
+{
+ //AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_VOLTE);
+ hfp_ag_cmd_conn_sco(BtAvrcpSrvGetActiveAddr());
+
+}
+
+
+void cat1_disconn_sco_(void)
+{
+ //AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_VOLTE);
+ hfp_ag_cmd_disconn_sco(BtAvrcpSrvGetActiveAddr());
+
+}
+
+void cat1_set_headset_volume( unsigned char volume)
+{
+ //AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_VOLTE);
+ hfp_ag_set_volume(BtAvrcpSrvGetActiveAddr(),HFP_VOLUME_SPEAKER,volume);
+
+}
+
+
+// uint8_t type; /*!< @if Eng The format of the phone number provided, the region of value is 128-175
+// @else 电话号码类型,值范围是128-175 @endif */
+// uint8_t service; /*!< @if Eng Indicates which service this phone number relates to.
+// Shall be either 4 (voice) or 5 (fax). See @ref hfp_ag_cnum_service_t
+// @else 服务类型,协议支持4或5,见 @ref hfp_ag_cnum_service_t @endif */
+// uint8_t num_len; /*!< @if Eng The length of the phone number @else 电话号码长度 @endif */
+// int8_t number[HFP_AG_PHONENUM_MAX_DIGITS]; /*!< @if Eng Subscriber number, the length shall be 32
+// @else 订阅号码,最大长度是32 @endif */
+// uint8_t name_len; /*!< @if Eng Length of subaddr @else 子地址长度 @endif */
+// int8_t alpha_str[1]; /*!< @if Eng string type subaddress of format specified by <cli_validity>
+// @else 子地址,协议默认是0 @endif */
+
+
+int cat1_ag_send_call_event( uint32_t event_topic, const char* info)
+{
+ //AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_VOLTE);
+ int ret=0;
+
+ hfp_phone_info_t phone_info={0};
+ if(info!=nullptr)
+ {
+ phone_info.type=128;
+ phone_info.service=4;
+ phone_info.num_len=strlen(info);
+ memcpy_s(phone_info.number,HFP_AG_PHONENUM_MAX_DIGITS,info,phone_info.num_len);
+ phone_info.alpha_str[0]=0;
+ }
+
+ switch (event_topic)
+ {
+ case TOPIC_EVENT_CAT1_INCOMMING:
+ ret=hfp_ag_send_network_incoming_event(BtAvrcpSrvGetActiveAddr(),&phone_info);
+ break;
+ case TOPIC_EVENT_CAT1_CALLCONNTED:
+ ret=hfp_ag_send_answer_call_event(BtAvrcpSrvGetActiveAddr());
+ break;
+ case TOPIC_EVENT_CAT1_CALLENDED:
+ ret=hfp_ag_send_finish_call_event(BtAvrcpSrvGetActiveAddr(),HFP_AG_CANCELED_LASTCALL);
+ break;
+ case TOPIC_EVENT_CAT1_CALLDIAL:
+ ret=hfp_ag_send_originate_call_event(BtAvrcpSrvGetActiveAddr());
+ break;
+ default:
+ ret=ERRCODE_BT_FAIL;
+ break;
+ }
+ return ret;
+}
+
+
+
+// #ifdef __cplusplus
+// }
+// #endif
static std::shared_ptr<AudioStreamOut> g_stream_out_downink = nullptr;
#endif
+
+static std::shared_ptr<AudioStreamIn> g_stream_in_uplink = nullptr;
+static std::shared_ptr<AudioStreamIn> g_stream_in_downink = nullptr;
+static std::shared_ptr<AudioStreamOut> g_stream_out_uplink = nullptr;
+static std::shared_ptr<AudioStreamOut> g_stream_out_downink = nullptr;
+
+
static int32_t StartVoiceCall(const char **param);
static int32_t StopVoiceCall(const char **param);
static int32_t VoiceCallSetVolume(const char **param);
static int32_t VoiceCAllSeaEnable(const char **param);
static int32_t VoiceCallMicMute(const char **param);
+static int32_t StartHFPVoiceCall(const char **param);
typedef struct {
char cmd[MEDIA_CMD_LEN_MAX];
{ "setvolume", VoiceCallSetVolume },
{ "seaenable", VoiceCAllSeaEnable },
{ "mute", VoiceCallMicMute },
+ { "startSCO",StartHFPVoiceCall}
};
class VoiceCallVolteInterruptListener : public InterruptListener {
}
}
+
+static void NO_LOCAL_VOICE_CALL_DeinitVoiceCallVolteResources(VoiceCallVolteContext *context)
+{
+ (void)g_stream_in_uplink.reset();
+ (void)g_stream_out_uplink.reset();
+ (void)g_stream_in_downink.reset();
+ (void)g_stream_out_downink.reset();
+
+ (void)MediaThreadCondDestroy(&context->cond);
+ (void)MediaMutexDestroy(&context->mutex);
+
+ if (g_voiceCallVolteContext != nullptr) {
+ free(g_voiceCallVolteContext);
+ g_voiceCallVolteContext = nullptr;
+ }
+}
+
static bool InitVoiceCallVolteResources(VoiceCallVolteContext *context)
{
context->mutex = MediaMutexCreate(nullptr);
return true;
}
+static bool NO_LOCAL_VOICE_CALL_RequsetAudioFocus(VoiceCallVolteContext *context)
+{
+ bool success;
+
+ success = g_amInstance.Initialize();
+ if (!success) {
+ MEDIA_ERR_LOG("audiomanager init failed");
+ return false;
+ }
+
+ AudioSession sessionId;
+
+ sessionId = g_amInstance.MakeSessionId();
+
+ if (sessionId == AUDIO_SESSION_ID_NONE) {
+ MEDIA_ERR_LOG("audio session id invalid");
+ return false;
+ }
+
+
+ std::shared_ptr<VoiceCallVolteInterruptListener> interruptListener =
+ std::make_shared<VoiceCallVolteInterruptListener>(context);
+ if (interruptListener == nullptr || interruptListener.get() == nullptr) {
+ MEDIA_ERR_LOG("voice call volte interrupt listener is nullptr");
+ return false;
+ }
+
+ AudioInterrupt interrupt = { AUDIO_STREAM_VOICE_CALL_VOLTE, sessionId, interruptListener };
+ if (g_amInstance.ActivateAudioInterrupt(interrupt) == INTERRUPT_FAILED) {
+ MEDIA_ERR_LOG("activate audio interrupt failed");
+ return false;
+ }
+
+ context->sessionId = sessionId;
+ context->interrupt = interrupt;
+
+
+ return true;
+}
+
+
+
+
#ifdef LOCAL_VOICE_CALL
static bool ReleaseAudioFocus(void)
{
}
#endif
+static bool ReleaseAudioFocus_HFP(VoiceCallVolteContext *context)
+{
+ if (g_amInstance.DeactivateAudioInterrupt(context->interrupt) != 0) {
+ MEDIA_ERR_LOG("deactivate audio interrupt failed");
+ return false;
+ }
+ return true;
+}
+
+
+
static void *VoiceCallVolteThread(void *priv)
{
VoiceCallVolteContext *context = (VoiceCallVolteContext *)priv;
return ret;
}
+
+////////////////////////////////////CAT1蓝牙SCO音频/////////////////////////////////////////
+
+
+static int32_t RunVoiceCallVolte_NO_LOCAL_VOICE_CALL(VoiceCallVolteContext *context)
+{
+ bool success = InitVoiceCallVolteResources(context);
+ if (!success) {
+ MEDIA_ERR_LOG("init voice call volte resources failed");
+ return -1;
+ }
+
+ int32_t ret = g_amInstance.SetDeviceConnectionState(IN_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set sco in device connect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set sco out device connect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(IN_MODEM_HEADSET, AUDIO_DEVICE_CONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set modem headset in device connect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(OUT_MODEM_HEADSET, AUDIO_DEVICE_CONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set modem headset out device connect failed");
+ }
+
+ g_stream_in_uplink = std::make_shared<AudioStreamIn>();
+
+ CapturerInputConfig captureConfig = {};
+ captureConfig.audioFormat = mSBC;
+ captureConfig.channelCount = 1;
+ captureConfig.linkDir = AUDIO_UP_LINK;
+ captureConfig.sampleRate = 16000;
+ captureConfig.sessionID = context->sessionId;
+ captureConfig.streamType = AUDIO_STREAM_VOICE_CALL_VOLTE;
+
+ ret = g_stream_in_uplink->Init(captureConfig);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in uplink init failed");
+ }
+
+ g_stream_out_uplink = std::make_shared<AudioStreamOut>();
+ // 16000 32000 44100 48000
+ AudioRendererConfig renderConfig = {};
+ renderConfig.audioFormat = mSBC;
+ renderConfig.channelCount = 1;
+ renderConfig.linkDir = AUDIO_UP_LINK;
+ renderConfig.sampleRate = 16000;
+ renderConfig.sessionID = context->sessionId;
+ renderConfig.streamType = AUDIO_STREAM_VOICE_CALL_VOLTE;
+
+ ret = g_stream_out_uplink->Init(renderConfig);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out uplink init failed");
+ }
+
+ //下行
+ g_stream_in_downink = std::make_shared<AudioStreamIn>();
+
+ captureConfig.audioFormat = mSBC;
+ captureConfig.channelCount = 1;
+ captureConfig.linkDir = AUDIO_DOWN_LINK;
+ captureConfig.sampleRate = 16000;
+ captureConfig.sessionID = context->sessionId;
+ captureConfig.streamType = AUDIO_STREAM_VOICE_CALL_VOLTE;
+
+ ret = g_stream_in_downink->Init(captureConfig);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in downink init failed");
+ }
+
+ g_stream_out_downink = std::make_shared<AudioStreamOut>();
+
+ renderConfig.audioFormat = mSBC;
+ renderConfig.channelCount = 1;
+ renderConfig.linkDir = AUDIO_DOWN_LINK;
+ renderConfig.sampleRate = 16000;
+ renderConfig.sessionID = context->sessionId;
+ renderConfig.streamType = AUDIO_STREAM_VOICE_CALL_VOLTE;
+
+ ret = g_stream_out_downink->Init(renderConfig);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out downink init failed");
+ }
+
+ ret = g_stream_in_uplink->Start();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in uplink start failed");
+ }
+
+ ret = g_stream_out_uplink->Play();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out uplink play failed");
+ }
+
+ ret = g_stream_in_downink->Start();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in downink start failed");
+ }
+
+ ret = g_stream_out_downink->Play();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out downink play failed");
+ }
+
+ uint32_t asoUplinkChannelId = 0;
+ g_stream_out_uplink->GetCurrentChannelId(asoUplinkChannelId);
+
+ MEDIA_INFO_LOG("asoUplinkChannelId: 0x%x", asoUplinkChannelId);
+
+ g_stream_in_uplink->AttachBackend(asoUplinkChannelId);
+
+ uint32_t asiDownlinkChannelId = 0;
+ g_stream_in_downink->GetCurrentChannelId(asiDownlinkChannelId);
+
+ MEDIA_INFO_LOG("asiDownlinkChannelId: 0x%x", asiDownlinkChannelId);
+
+ g_stream_out_downink->AttachFrontend(asiDownlinkChannelId);
+
+
+ MediaMutexLock(context->mutex);
+ while (!context->isVoiceCallVolteStopped) {
+ MediaThreadCondWait(context->cond, context->mutex);
+ }
+ MediaMutexUnLock(context->mutex);
+
+
+ ret = g_stream_in_uplink->Stop();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in uplink stop failed");
+ }
+
+ ret = g_stream_out_uplink->Stop();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out uplink stop failed");
+ }
+
+ ret = g_stream_in_downink->Stop();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in downink stop failed");
+ }
+
+ ret = g_stream_out_downink->Stop();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out downink stop failed");
+ }
+
+ ret = g_stream_in_uplink->Release();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in uplink release failed");
+ }
+
+ ret = g_stream_out_uplink->Release();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out uplink release failed");
+ }
+
+ ret = g_stream_in_downink->Release();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream in downink release failed");
+ }
+
+ ret = g_stream_out_downink->Release();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("audio stream out downink release failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(IN_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set sco in device disconnect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set sco out device disconnect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(IN_MODEM_HEADSET, AUDIO_DEVICE_DISCONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set modem headset in device disconnect failed");
+ }
+
+ ret = g_amInstance.SetDeviceConnectionState(OUT_MODEM_HEADSET, AUDIO_DEVICE_DISCONNECTED);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("set modem headset out device disconnect failed");
+ }
+
+
+ NO_LOCAL_VOICE_CALL_DeinitVoiceCallVolteResources(context);
+
+ return 0;
+}
+
+
+
+static void *VoiceCallVolteHFPThread(void *priv)
+{
+ VoiceCallVolteContext *context = (VoiceCallVolteContext *)priv;
+
+ bool success = NO_LOCAL_VOICE_CALL_RequsetAudioFocus(context);
+ if (!success) {
+ MEDIA_ERR_LOG("requset audio focus failed");
+ return nullptr;
+ }
+
+ int32_t ret = RunVoiceCallVolte_NO_LOCAL_VOICE_CALL(context);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("run voice call volte failed");
+
+ (void)ReleaseAudioFocus_HFP(context);
+ // (void)ReleaseAudioFocus();
+ return nullptr;
+ }
+
+ success = ReleaseAudioFocus_HFP(context);
+ // success = ReleaseAudioFocus();
+ if (!success) {
+ MEDIA_ERR_LOG("release audio focus failed");
+ return nullptr;
+ }
+ printf("VoiceCallVolteHFPThread END");
+ return nullptr;
+}
+
+
+
+static int32_t StartHFPVoiceCall(const char **param)
+{
+ MediaMutexLock(g_voiceCallVolteContextMutex);
+ if (g_voiceCallVolteContext != nullptr) {
+ MEDIA_ERR_LOG("invalid operation");
+ return -1;
+ }
+
+ // 1. create VoiceCallVolteContext
+ g_voiceCallVolteContext = (VoiceCallVolteContext *)malloc(sizeof(VoiceCallVolteContext));
+ if (g_voiceCallVolteContext == nullptr) {
+ MEDIA_ERR_LOG("malloc failed");
+ MediaMutexUnLock(g_voiceCallVolteContextMutex);
+ return -1;
+ }
+ if (memset_s(g_voiceCallVolteContext, sizeof(VoiceCallVolteContext), 0, sizeof(VoiceCallVolteContext)) != EOK) {
+ MEDIA_ERR_LOG("memset_s failed");
+ }
+ MediaMutexUnLock(g_voiceCallVolteContextMutex);
+
+ // 3. create voice call volte thread
+ MediaThreadattr attr = { "VoiceCallVolteThread", 0x2000, THREAD_SCHED_INVALID, 0, true };
+ MediaThreadIdHandle taskHandle = MediaThreadCreate(VoiceCallVolteHFPThread, g_voiceCallVolteContext, &attr);
+ if (taskHandle == nullptr) {
+ MEDIA_ERR_LOG("create voice call volte thread failed");
+ free(g_voiceCallVolteContext);
+ g_voiceCallVolteContext = nullptr;
+ return -1;
+ }
+
+ // will free g_voiceCallVolteContext when sub thread play exit
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#ifdef __cplusplus
};
#endif