/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved. * * Description: TjdPhoneService.cpp * * Author: luziquan@ss-tjd.com * * Create: 2025-08-16 *--------------------------------------------------------------------------*/ #include "TjdPhoneService.h" #include "TjdPhoneAudio.h" #include "TjdPhoneContacts.h" #include "TjdUiMsgCenter.h" #include "TjdUiSettingCenter.h" #include "audio_base_type.h" #include "bts_pbap.h" #include "graphic_service.h" #include "service_bt.h" #include "sys_config.h" #include "thread_adapter.h" #include "ui_screennotify.h" #include #include #include #include #include #include extern "C" { #include "power_display_service.h" } #define ENABLE_PRINT_INFO 1 #if ENABLE_PRINT_INFO #define static_print_warn(...) sys_phone_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_phone_log_e(__VA_ARGS__) // 错误信息打印一般常开 #define static_print_debug(...) sys_phone_log_d(__VA_ARGS__) // 调试信息打印一般常开 #else #define static_print_warn(...) #define static_print_error(...) #define static_print_debug(...) #endif typedef enum { AUDIO_UNKNOW = 0, AUDIO_ACT_INTERRUPT_WATCH_RING, // 手表铃声焦点 AUDIO_ACT_INTERRUPT_BT_SCO, // 蓝牙通话焦点 AUDIO_CONN_IN_BT_SCO, AUDIO_CONN_OUT_BT_SCO, AUDIO_STREAM_INIT, AUDIO_STREAM_START_SCO, AUDIO_STREAM_START_DN, AUDIO_STREAM_START_UP, } AudioState; #define TJD_CALL_LOG_DIR "/user/tjd_phone" #define TJD_CALL_LOG_PATH (TJD_CALL_LOG_DIR "/calllog.bin") #define TJD_CALL_TMP_LOG_PATH (TJD_CALL_LOG_DIR "/calltmplog.bin") #define INVALID_PHONE_SERVICE_VALUE (-1) static uint32_t g_scoFlag = HFP_SCO_STATE_DISCONNECTED; // sco连接状态,同时也表示通话在手表还是在手机 static uint32_t g_btConnState = PROFILE_STATE_DISCONNECTED; // 蓝牙连接状态 static uint32_t g_currCallState = HFP_HF_CALL_STATE_FINISHED; // 电话呼叫状态类型。 static bool g_completeCallFlag = false; // 完整通话流程:从incoming、dialing或alerting开始才算完整 static uint32_t g_call_codec = mSBC; // 通话编解码类型 static bd_addr_t g_bdAddr; // 设备的蓝牙地址 static uint32 g_currCallNum = 0; // 当前通话路数 static MutexId g_audioMutex; static ContactsInfo g_callList[MULTI_CALL_MAX_NUME]; static uint32_t g_finishOperate = OPERATE_NON_WATCH_FINISH; static uint32_t g_audioState = AUDIO_UNKNOW; static uint32_t g_interval = 5; static int g_hdlUpMic = INVALID_PHONE_SERVICE_VALUE; static int g_hdlUpSco = INVALID_PHONE_SERVICE_VALUE; static int g_hdlDnSpk = INVALID_PHONE_SERVICE_VALUE; static int g_hdlDnSco = INVALID_PHONE_SERVICE_VALUE; bd_addr_t *GetHfpBdAddr(void) { return &g_bdAddr; } static void PostGraphicEvent(void (*fun)(void)) { static_print_debug("[PostGraphicEvent] start"); GraphicService::GetInstance()->PostGraphicEvent(*fun); } static PhoneServiceCb g_callChanged; int RegisterPhoneCallChangedCb(PhoneServiceCb *phoneServiceFun) { if (phoneServiceFun == nullptr) { return OHOS_FAILURE; } (void)memcpy_s(&g_callChanged, sizeof(g_callChanged), phoneServiceFun, sizeof(g_callChanged)); return OHOS_SUCCESS; } static void ScreenTurnOn(int32_t timeout) { #if defined(SUPPORT_POWER_MANAGER) g_interval = get_back_to_home_interval(); set_back_to_home_interval(0xFFFFFFFF); const power_display_svr_api_t *display_api = power_display_svr_get_api(); if (display_api->get_screen_state() != SCREEN_ON) { display_api->turn_on_screen(); } display_api->set_screen_set_keepon_timeout(timeout); #endif return; } static void ScreenTurnOff(void) { #if defined(SUPPORT_POWER_MANAGER) set_back_to_home_interval(g_interval); const power_display_svr_api_t *display_api = power_display_svr_get_api(); display_api->set_screen_set_keepon_timeout(0); #endif return; } static void PhoneServiceScreenCtr(bool turnOnFlag) { if (turnOnFlag) { ScreenTurnOn(-1); } else { ScreenTurnOff(); } } // 手表主动拨打电话 int DialCallOut(const unsigned char *number, unsigned char len) { int ret; unsigned char *tel = nullptr; static_print_debug("[DialCall] start"); if (g_btConnState != PROFILE_STATE_CONNECTED) { static_print_error("[DialCall] BT connStatus: 0x%X", g_btConnState); return OHOS_FAILURE; } // 有通话时,不允许拨出电话 if (g_currCallNum > 0 || len > MAX_PHONE_NUM || number == nullptr) { static_print_error("[DialCall] g_currCallNum:%d", g_currCallNum); return OHOS_FAILURE; } tel = (unsigned char *)malloc(len + 1); if (tel == nullptr) { static_print_error("[DialCall] malloc tel error"); return OHOS_FAILURE; } (void)memcpy_s(tel, len, number, len); *(tel + len) = '\0'; ret = hfp_hf_start_dial(&g_bdAddr, tel, len); if (ret != ERRCODE_BT_SUCCESS) { static_print_error("[DialCall] hfp_hf_start_dial ret %d", ret); free(tel); return OHOS_FAILURE; } static_print_debug("[DialCall] success!"); free(tel); return OHOS_SUCCESS; } // 手表主动接听 int AnswerCallIn(void) { static_print_debug("[AcceptIncomingCall] start"); int32_t ret; ContactsInfo *phoneCall = nullptr; ContactsInfo *tmp = g_callList; if (g_btConnState != PROFILE_STATE_CONNECTED) { static_print_error("[AcceptIncomingCall] BT connStatus: 0x%X", g_btConnState); return OHOS_FAILURE; } for (int32_t i = 0; i < MULTI_CALL_MAX_NUME; i++) { if (tmp->lastStatus == HFP_HF_CALL_STATE_INCOMING || tmp->lastStatus == HFP_HF_CALL_STATE_WAITING) { phoneCall = tmp; break; } tmp++; } if (phoneCall == nullptr) { static_print_error("[AcceptIncomingCall] no incoming"); return OHOS_FAILURE; } phoneCall->operate = OPERATE_WATCH_ACTIVE; if (g_currCallNum > 1) { // 正在通话,有人呼入,接听呼入电话,挂起当前通话 ret = hfp_hf_accept_incoming_call(&g_bdAddr, HFP_HF_ACCEPT_CALL_ACTION_HOLD); } else { // 无人通话,有人呼入,接听呼入电话 ret = hfp_hf_accept_incoming_call(&g_bdAddr, HFP_HF_ACCEPT_CALL_ACTION_NONE); } if (ret != ERRCODE_BT_SUCCESS) { static_print_error("[AcceptIncomingCall] ret:%d", ret); phoneCall->operate = OPERATE_NO_OPE; return OHOS_FAILURE; } static_print_debug("[AcceptIncomingCall] success!"); return OHOS_SUCCESS; } // 手表拒接呼入来电,成功:0,失败:错误码 int RejectCallIn(void) { static_print_debug("[RejectIncomingCall] start"); ContactsInfo *phoneCall = nullptr; ContactsInfo *tmp = g_callList; if (g_btConnState != PROFILE_STATE_CONNECTED) { static_print_error("[RejectIncomingCall] BT connStatus: 0x%X", g_btConnState); return OHOS_FAILURE; } for (int32_t i = 0; i < MULTI_CALL_MAX_NUME; i++) { if (tmp->lastStatus == HFP_HF_CALL_STATE_INCOMING || tmp->lastStatus == HFP_HF_CALL_STATE_WAITING) { phoneCall = tmp; } tmp++; } if (phoneCall == nullptr) { static_print_error("[AcceptIncomingCall] no incoming"); return OHOS_SUCCESS; } int32_t ret = hfp_hf_reject_incoming_call(&g_bdAddr); if (ret != ERRCODE_BT_SUCCESS) { static_print_error("[RejectIncomingCall] ret:%d", ret); return OHOS_FAILURE; } g_finishOperate = OPERATE_WATCH_REJECT; static_print_debug("[RejectIncomingCall] success!"); return OHOS_SUCCESS; } // 手表结束通话 int DialCallFinish(void) { if (g_btConnState != PROFILE_STATE_CONNECTED) { static_print_error("[FinishCall] BT connStatus: 0x%X", g_btConnState); return OHOS_FAILURE; } if (g_currCallState != HFP_HF_CALL_STATE_ACTIVE && g_currCallState != HFP_HF_CALL_STATE_HELD && g_currCallState != HFP_HF_CALL_STATE_DIALING && g_currCallState != HFP_HF_CALL_STATE_ALERTING) { static_print_error("[FinishCall] g_currCallState:%d", g_currCallState); return OHOS_FAILURE; } int ret = hfp_hf_finish_call(&g_bdAddr); if (ret != ERRCODE_BT_SUCCESS) { static_print_error("[FinishCall] ret:%d", ret); return OHOS_FAILURE; } g_finishOperate = OPERATE_WATCH_FINISH; static_print_debug("FinishCall"); return OHOS_SUCCESS; } // 获取当前正在通话路数 int GetCurCallNumber(void) { return g_currCallNum; } static void CallChangedCb(const ContactsInfo *phoneCall) { if (g_callChanged.callChanged != nullptr) { g_callChanged.callChanged(phoneCall); } } static void ScoStatusCb(hfp_sco_connect_state_t state) { if (g_callChanged.scoStatusCb != nullptr) { g_callChanged.scoStatusCb(state); } } static void PhoneServiceErrorCallback(PhoneServiceErrorType type, int volume) { if (g_callChanged.phoneServiceErrorCb != nullptr) { g_callChanged.phoneServiceErrorCb(type, volume); } } static void CopyBdAddr(const bd_addr_t *bdAddr) { unsigned char addr[BD_ADDR_LEN] = {0}; if (strncmp((const char *)g_bdAddr.addr, (const char *)addr, BD_ADDR_LEN) == 0) { (void)memcpy_s(g_bdAddr.addr, BD_ADDR_LEN, bdAddr->addr, BD_ADDR_LEN); } } static void HfpIncomingEventPublish(uint16 topic, hfp_hf_calls_info_t callsInfo) { int32_t ret; uint32_t size = sizeof(hfp_hf_calls_info_t); static_print_debug("HfpIncomingEventPublish topic=%u!!", topic); TjdUiMsgEventPublish(topic, &callsInfo, size); } #pragma region 通话记录 // 获取当前通话记录 std::vector ReadCallLogs(void) { std::vector callLogs; FILE *fp = fopen(TJD_CALL_LOG_PATH, "rb"); if (fp == nullptr) { static_print_error("[ReadCallLogs] fopen %s failed!", TJD_CALL_LOG_PATH); return callLogs; } CallLogInfo info; while (fread(&info, sizeof(CallLogInfo), 1, fp) == 1) { static_print_debug("[ReadCallLogs] name %s, tel %s", info.name, info.tel); callLogs.push_back(info); } if (ferror(fp)) { static_print_error("[ReadCallLogs] fread failed!"); } fclose(fp); return callLogs; } // 通话记录初始化 static void CallListInit(void) { int i; g_currCallNum = 0; (void)memset_s(g_callList, sizeof(g_callList), 0, sizeof(g_callList)); for (i = 0; i < MULTI_CALL_MAX_NUME; i++) { (void)memset_s(g_callList[i].name, NAME_SIZE, '\0', NAME_SIZE); (void)memset_s(g_callList[i].tel, MAX_PHONE_NUM, '\0', MAX_PHONE_NUM); g_callList[i].lastStatus = HFP_HF_CALL_STATE_FINISHED; } } // 获取通话记录文件大小 static int GetCallLogFileSize(void) { int len = 0; FILE *fp = fopen(TJD_CALL_LOG_PATH, "rb"); if (fp == nullptr) { static_print_error("[GetCallLogFileSize] fopen %s failed", TJD_CALL_LOG_PATH); return 0; } fseek(fp, 0, SEEK_END); len = ftell(fp); fseek(fp, 0, SEEK_SET); fclose(fp); static_print_debug("[GetCallLogFileSize] len:%d", len); return len; } // 清空通话记录 static int ClearCallLogInfoFile(void) { FILE *fp = fopen(TJD_CALL_LOG_PATH, "wb"); if (fp == nullptr) { static_print_error("[ClearCallLogFile] fopen %s failed!", TJD_CALL_LOG_PATH); return OHOS_FAILURE; } fclose(fp); return OHOS_SUCCESS; } static ContactsInfo *FindCallInfoInCallList(const unsigned char *number, unsigned char numberLen) { int i; const char *str1 = nullptr; const char *str2 = nullptr; if (g_currCallNum == 0) { return nullptr; } for (i = 0; i < MULTI_CALL_MAX_NUME; i++) { if (numberLen != g_callList[i].telLen) { continue; } else { str1 = (const char *)number; str2 = (const char *)g_callList[i].tel; if (strncmp(str1, str2, numberLen) == 0) { return &g_callList[i]; } } } return nullptr; } // 通话记录添加 static void AddCurrCallToCallList(const hfp_hf_calls_info_t *call) { static_print_debug("[AddCurrCallToCallList] state:%d", call->state); if (call == nullptr || g_currCallNum >= MULTI_CALL_MAX_NUME || (call->state != HFP_HF_CALL_STATE_ACTIVE && call->state != HFP_HF_CALL_STATE_HELD && call->state != HFP_HF_CALL_STATE_ALERTING)) { return; } g_currCallNum++; int32_t tmp = g_currCallNum - 1; ContactsInfo *phoneCall = &g_callList[tmp]; if (call->state == HFP_HF_CALL_STATE_ACTIVE) { // 正在通话 phoneCall->operate = OPERATE_PHONE_ACTIVE; phoneCall->activeTime = time(nullptr); } else if (call->state == HFP_HF_CALL_STATE_HELD) { // 挂起 phoneCall->operate = OPERATE_PHONE_HOLD; phoneCall->activeTime = time(nullptr); } else if (call->state == HFP_HF_CALL_STATE_ALERTING) { // 呼出,对方响铃 phoneCall->operate = OPERATE_ALERTING; } // 使用通讯录接口获取当前电话对应的备注人名(通讯录待开发) phoneCall->lastStatus = call->state; phoneCall->creationTime = time(nullptr); int32_t ret = memcpy_s(phoneCall->tel, MAX_PHONE_NUM, call->number, call->number_len); if (ret != EOK) { static_print_error("[AddCurrCallToCallList] copy tel ret:%d", ret); } phoneCall->telLen = call->number_len; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); static_print_debug("[AddCurrCallToCallList] end"); static_print_debug("[AddCurrCallToCallList] name:%s, tel:%s, telLen:%d", phoneCall->name, phoneCall->tel, phoneCall->telLen); // 通知手表电话呼入 CallChangedCb(phoneCall); } static int CopyPhoneLogToTmpLog(void) { FILE *fp = nullptr; FILE *ftp = nullptr; CallLogInfo *info = nullptr; int retLen; int fileSize = GetCallLogFileSize(); if (fileSize == OHOS_FAILURE || fileSize == 0) { return fileSize; } retLen = fileSize - sizeof(CallLogInfo); if (retLen == 0) { return ClearCallLogInfoFile(); // 只有一条记录,清空通话记录 } fp = fopen(TJD_CALL_LOG_PATH, "rb"); if (fp == nullptr) { return OHOS_FAILURE; } ftp = fopen(TJD_CALL_TMP_LOG_PATH, "wb+"); if (ftp == nullptr) { fclose(fp); return OHOS_FAILURE; } info = (CallLogInfo *)malloc(fileSize); if (info == nullptr) { fclose(fp); fclose(ftp); return OHOS_FAILURE; } (void)memset_s(info, fileSize, 0, fileSize); if (fread(info, fileSize, 1, fp) != 1) { retLen = OHOS_FAILURE; goto END; } if (fwrite((info + 1), retLen, 1, ftp) != 1) { retLen = OHOS_FAILURE; goto END; } END: fclose(fp); fclose(ftp); free(info); info = nullptr; return retLen; } // 删除第一条通话记录 static int RemoveFirstCallLog(void) { FILE *fp = nullptr; FILE *ftp = nullptr; CallLogInfo *info = nullptr; int ret = OHOS_SUCCESS; int fileSize = CopyPhoneLogToTmpLog(); if (fileSize == OHOS_FAILURE || fileSize == 0) { return fileSize; } fp = fopen(TJD_CALL_LOG_PATH, "wb+"); if (fp == nullptr) { return OHOS_FAILURE; } ftp = fopen(TJD_CALL_TMP_LOG_PATH, "rb"); if (ftp == nullptr) { fclose(fp); return OHOS_FAILURE; } info = (CallLogInfo *)malloc(fileSize); if (info == nullptr) { fclose(fp); fclose(ftp); return OHOS_FAILURE; } (void)memset_s(info, fileSize, 0, fileSize); if (fread(info, fileSize, 1, ftp) != 1) { ret = OHOS_FAILURE; goto END; } if (fwrite(info, fileSize, 1, fp) != 1) { ret = OHOS_FAILURE; goto END; } END: fclose(fp); fclose(ftp); free(info); info = nullptr; return ret; } static void AddToCallLog(CallLogInfo *info) { FILE *fp = nullptr; size_t ret; fp = fopen(TJD_CALL_LOG_PATH, "ab"); if (fp == nullptr) { static_print_error("[AddToCallLog] fopen %s failed!", TJD_CALL_LOG_PATH); return; } ret = fwrite(info, sizeof(CallLogInfo), 1, fp); if (ret != 1) { static_print_error("[AddToCallLog] fwrite failed! ret:%d", ret); } static_print_debug("[AddToCallLog] fwrite :%d", ret); fclose(fp); static_print_debug("[AddToCallLog] success! name:%s, tel:%s, telLen:%d", info->name, info->tel, info->telLen); } // 添加通话记录 static void AddToCallLogPro(ContactsInfo *callInfo) { if (callInfo == nullptr) { return; } int fileSize = GetCallLogFileSize(); int num = fileSize / sizeof(CallLogInfo); if (num >= CALL_LOG_MAX_NUM) { int ret = RemoveFirstCallLog(); if (ret == OHOS_FAILURE) { static_print_error("[AddToCallLogPro] RemoveFirstCallLog error"); return; } } CallLogInfo info; (void)memset_s(info.name, NAME_SIZE, '\0', NAME_SIZE); (void)memset_s(info.tel, MAX_PHONE_NUM, '\0', MAX_PHONE_NUM); int ret = memcpy_s(info.name, NAME_SIZE, callInfo->name, callInfo->nameLen); if (ret != EOK) { info.nameLen = 0; } else { info.nameLen = callInfo->nameLen; } ret = memcpy_s(info.tel, MAX_PHONE_NUM, callInfo->unitCalls.number, callInfo->unitCalls.number_len); if (ret != EOK) { info.telLen = 0; } else { info.telLen = callInfo->unitCalls.number_len; } info.creationTime = callInfo->creationTime; if (callInfo->lastStatus == HFP_HF_CALL_STATE_ACTIVE || callInfo->lastStatus == HFP_HF_CALL_STATE_HELD || callInfo->lastStatus == HFP_HF_CALL_STATE_RESPONSE_HELD) { info.callDurTime = time(nullptr) - callInfo->activeTime; } else { info.callDurTime = 0; } if (callInfo->lastStatus == HFP_HF_CALL_STATE_INCOMING || callInfo->lastStatus == HFP_HF_CALL_STATE_WAITING) { info.status = CALL_MISSED; } else if (callInfo->unitCalls.outgoing == 1) { info.status = CALL_OUTGOING; } else { info.status = CALL_INCOMING; } AddToCallLog(&info); } #pragma endregion static void BtDisconnectedPro(void) { g_btConnState = PROFILE_STATE_DISCONNECTED; (void)memset_s(g_bdAddr.addr, BD_ADDR_LEN, 0, BD_ADDR_LEN); // 通知APP蓝牙断开连接 PhoneServiceErrorCallback(ERROR_BT, PROFILE_STATE_DISCONNECTED); CallListInit(); if (g_currCallState == HFP_HF_CALL_STATE_INCOMING) { /* 处理呼入阶段,取消手表配对 */ hfp_hf_calls_info_t call = {}; HfpIncomingEventPublish(TOPIC_EVENT_HFP_FINISHED, call); } g_currCallState = HFP_HF_CALL_STATE_FINISHED; g_scoFlag = HFP_SCO_STATE_DISCONNECTED; g_completeCallFlag = false; } static bool IsCompleteCallFlow(void) { return g_completeCallFlag; } // 获取当前通话音量大小 (0 - 15) // hfp音量范围 0-15, media 音量范围 0-100 unsigned char GetHFPCallCurrVolume(void) { TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); int32_t volume = audio.PhoneAudioGetVolume(); int32_t minVolume = audio.PhoneAudioGetMinVolume(); int32_t maxVolume = audio.PhoneAudioGetMaxVolume(); unsigned char hfpVolume = (unsigned char)((volume * CALL_VOLUME_MAX) / (maxVolume - minVolume)); // 转换 if (volume != 0 && hfpVolume == 0) { hfpVolume = 1; } static_print_debug("[GetHFPCallCurrVolume] volume:%d, minVolume:%d, maxVolume:%d, hfpVolume:%d", volume, minVolume, maxVolume, hfpVolume); return hfpVolume; } void SetHFPSpeakerVolume(unsigned char hfpVolume) { TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); static_print_debug("[SetHFPSpeakerVolume] start, hfpVolume:%d", hfpVolume); int32_t minVolume = audio.PhoneAudioGetMinVolume(); int32_t maxVolume = audio.PhoneAudioGetMaxVolume(); int32_t volume = hfpVolume * (maxVolume - minVolume) / CALL_VOLUME_MAX; // 转换 static_print_debug("[SetHFPSpeakerVolume] minVolume:%d, maxVolume:%d, volume:%d", minVolume, maxVolume, volume); int32_t ret = audio.PhoneAudioSetVolume(volume); if (!ret) { static_print_error("[SetHFPSpeakerVolume] PhoneAudioSetVolume ret:%d", ret); return; } ret = hfp_hf_set_volume(&g_bdAddr, HFP_VOLUME_SPEAKER, hfpVolume); if (ret != ERRCODE_BT_SUCCESS) { static_print_error("[SetHFPSpeakerVolume] set_volume ret:%d, hfpVolume:%d", ret, hfpVolume); return; } static_print_debug("[SetHFPSpeakerVolume] success!"); } // 通话状态变化--接听流程处理 static void CallChangeActivePro(const hfp_hf_calls_info_t *call) { if (call == nullptr) { return; } // 如果通话记录中没有该通话,添加到通话记录中,然后通知通话转移到手机 ContactsInfo *phoneCall = nullptr; phoneCall = FindCallInfoInCallList((const unsigned char *)call->number, call->number_len); if (phoneCall == nullptr) { static_print_debug("[CallChangeActivePro] Active no this call"); AddCurrCallToCallList(call); // TransCallToMobilePhone(); return; } if (phoneCall->lastStatus == HFP_HF_CALL_STATE_HELD && IsCompleteCallFlow()) { // 挂起状态切换到接听状态 phoneCall->operate = OPERATE_WATCH_ACTIVE; } else if (phoneCall->lastStatus == HFP_HF_CALL_STATE_HELD && (!IsCompleteCallFlow())) { phoneCall->operate = OPERATE_PHONE_ACTIVE; } else if (phoneCall->operate == OPERATE_WATCH_ACTIVE) { // 手表接听 // 不做操作 } else { if (phoneCall->unitCalls.outgoing == 1 && (phoneCall->lastStatus == HFP_HF_CALL_STATE_DIALING || phoneCall->lastStatus == HFP_HF_CALL_STATE_ALERTING)) { phoneCall->operate = OPERATE_PEER_ACTIVE; // 对方接听 } else { // 手机接听 phoneCall->operate = OPERATE_PHONE_ACTIVE; static_print_debug("[CallChangeActivePro] phone active!"); } } if (phoneCall->activeTime == 0 && (phoneCall->lastStatus == HFP_HF_CALL_STATE_DIALING || phoneCall->lastStatus == HFP_HF_CALL_STATE_ALERTING || phoneCall->lastStatus == HFP_HF_CALL_STATE_INCOMING || phoneCall->lastStatus == HFP_HF_CALL_STATE_WAITING)) { phoneCall->activeTime = time(nullptr); } phoneCall->lastStatus = call->state; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); if (phoneCall->operate == OPERATE_PHONE_ACTIVE) { // 发布电话接听事件,手表关闭来电通知 HfpIncomingEventPublish(TOPIC_EVENT_HFP_PHONE_ACTIVE, phoneCall->unitCalls); } else if (phoneCall->operate == OPERATE_WATCH_ACTIVE && g_scoFlag == HFP_SCO_STATE_CONNECTED) { // 发布手表接听事件,通知切换接听界面 HfpIncomingEventPublish(TOPIC_EVENT_HFP_WATCH_ACTIVE, phoneCall->unitCalls); } // 通知手表触发接听 CallChangedCb(phoneCall); } // 通话状态变化--挂起通话(当前只有手机挂起触发(并且手表不需感知),手表不支持挂起触发,对方挂起不感知) static void CallChangeHeldPro(const hfp_hf_calls_info_t *call) { if (call == nullptr) { return; } ContactsInfo *phoneCall = FindCallInfoInCallList((const unsigned char *)call->number, call->number_len); if (phoneCall == nullptr) { static_print_debug("[CallChangeHeldPro] Held no this call"); AddCurrCallToCallList(call); return; } // 手机挂起通话 phoneCall->operate = OPERATE_PHONE_HOLD; if (phoneCall->lastStatus == HFP_HF_CALL_STATE_INCOMING || phoneCall->lastStatus == HFP_HF_CALL_STATE_WAITING) { phoneCall->activeTime = time(nullptr); } phoneCall->lastStatus = call->state; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); // 通知手表触发挂起 CallChangedCb(phoneCall); } // 通话状态变化--呼出,正在拨号处理 static void CallChangeDialPro(const hfp_hf_calls_info_t *call) { if (call == nullptr) { return; } g_currCallNum++; int32_t tmp = g_currCallNum - 1; ContactsInfo *phoneCall = &g_callList[tmp]; // 使用通讯录接口获取当前电话对应的备注人名(通讯录待开发) phoneCall->operate = OPERATE_DIALING; phoneCall->lastStatus = call->state; phoneCall->creationTime = time(nullptr); int32_t ret = memcpy_s(phoneCall->tel, MAX_PHONE_NUM, call->number, call->number_len); if (ret != EOK) { static_print_error("[CallChangeDialPro] copy tel ret:%d", ret); } phoneCall->telLen = call->number_len; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); // 通知手表正在拨号 CallChangedCb(phoneCall); } // 通话状态变化--呼出,对方响铃 static void CallChangeAlertPro(const hfp_hf_calls_info_t *call) { ContactsInfo *phoneCall = nullptr; if (call == nullptr) { return; } phoneCall = FindCallInfoInCallList((const unsigned char *)call->number, call->number_len); if (phoneCall == nullptr) { static_print_debug("[CallChangeAlertPro] Alert no this call"); AddCurrCallToCallList(call); return; } phoneCall->operate = OPERATE_ALERTING; phoneCall->lastStatus = call->state; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); // 通知手表正对方响铃 CallChangedCb(phoneCall); } // 通话状态变化--呼入处理 static void CallChangeIncomePro(const hfp_hf_calls_info_t *call) { if (call == nullptr || g_currCallNum >= MULTI_CALL_MAX_NUME || (call->state != HFP_HF_CALL_STATE_INCOMING && call->state != HFP_HF_CALL_STATE_WAITING)) { return; } ContactsInfo *phoneCall = FindCallInfoInCallList((const unsigned char *)call->number, call->number_len); if (phoneCall != nullptr) { // 通话状态由呼入等待转换成呼入情况 } else { g_currCallNum++; int32_t tmp = g_currCallNum - 1; phoneCall = &g_callList[tmp]; } // 使用通讯录接口获取当前电话对应的备注人名(通讯录待开发) if (call->state == HFP_HF_CALL_STATE_INCOMING) { phoneCall->operate = OPERATE_INCOMING; } else { phoneCall->operate = OPERATE_WAITING; } phoneCall->lastStatus = call->state; phoneCall->creationTime = time(nullptr); int32_t ret = memcpy_s(phoneCall->tel, MAX_PHONE_NUM, call->number, call->number_len); if (ret != EOK) { static_print_error("[CallChangeIncomePro] copy tel ret:%d", ret); } phoneCall->telLen = call->number_len; (void)memcpy_s(&phoneCall->unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); // 发布电话呼入事件 HfpIncomingEventPublish(TJDUI_TOPIC_EVENT_HFP_INCOMMING, phoneCall->unitCalls); // 通知手表电话呼入 CallChangedCb(phoneCall); } // 通话状态变化--拒接/结束流程处理 static void CallChangeFinishPro(const hfp_hf_calls_info_t *call) { ContactsInfo *phoneCall = nullptr; ContactsInfo tmp; static_print_debug("[CallChangeFinishPro] start scoFlag:%d, CallNum:%d", g_scoFlag, g_currCallNum); if (call == nullptr || g_currCallNum == 0) { return; } phoneCall = FindCallInfoInCallList((const unsigned char *)call->number, call->number_len); if (phoneCall == nullptr) { static_print_debug("[CallChangeFinishPro] Finish no this call"); return; } if (g_finishOperate == OPERATE_WATCH_FINISH) { phoneCall->operate = OPERATE_WATCH_FINISH; } else if (g_finishOperate == OPERATE_WATCH_REJECT) { phoneCall->operate = OPERATE_WATCH_REJECT; } else { phoneCall->operate = OPERATE_NON_WATCH_FINISH; } g_finishOperate = OPERATE_NON_WATCH_FINISH; g_currCallNum--; phoneCall->lastStatus = HFP_HF_CALL_STATE_FINISHED; const ContactInfo *contactInfo = FindContactOfNumber((const unsigned char *)call->number, call->number_len); if (contactInfo != nullptr) { (void)memcpy_s(phoneCall->name, NAME_SIZE, contactInfo->name.c_str(), contactInfo->name.size()); } (void)memcpy_s(&tmp, sizeof(ContactsInfo), phoneCall, sizeof(ContactsInfo)); (void)memcpy_s(&tmp.unitCalls, sizeof(hfp_hf_calls_info_t), call, sizeof(hfp_hf_calls_info_t)); (void)memset_s(phoneCall, sizeof(ContactsInfo), 0, sizeof(ContactsInfo)); (void)memset_s(phoneCall->name, NAME_SIZE, '\0', NAME_SIZE); (void)memset_s(phoneCall->tel, MAX_PHONE_NUM, '\0', MAX_PHONE_NUM); // 添加通话记录 AddToCallLogPro(&tmp); // 发布电话结束事件 HfpIncomingEventPublish(TOPIC_EVENT_HFP_FINISHED, phoneCall->unitCalls); // 通知手表通话结束 CallChangedCb(&tmp); static_print_debug("[CallChangeFinishPro] end activeTime:%d, creation_time:%d", tmp.activeTime, tmp.unitCalls.creation_time); static_print_debug("[CallChangeFinishPro] end scoFlag:%d, CallNum:%d", g_scoFlag, g_currCallNum); } // 蓝牙状态连接 static void ConnStateChanged(const bd_addr_t *bdAddr, profile_connect_state_t state) { int ret = 0; switch (state) { case PROFILE_STATE_CONNECTING: // 蓝牙正在连接 static_print_debug("[ConnStateChanged] BT connecting"); break; case PROFILE_STATE_CONNECTED: // 蓝牙连接成功 static_print_debug("[ConnStateChanged] BT connected"); g_btConnState = PROFILE_STATE_CONNECTED; CopyBdAddr(bdAddr); // SendMsgToUIService(BT_CONNECTED_TO_UI, 0, nullptr, 0); // SendMsgToMsgCenterService(BT_CONNECTED_TO_MSGCENTER, 0, nullptr, 0); break; case PROFILE_STATE_DISCONNECTING: // 蓝牙连接断连 static_print_debug("[ConnStateChanged] BT disconnecting"); break; case PROFILE_STATE_DISCONNECTED: // 蓝牙断开连接 static_print_debug("[ConnStateChanged] BT disconnected"); BtDisconnectedPro(); // SendMsgToUIService(BT_DISCONNECTED_TO_UI, 0, nullptr, 0); // SendMsgToMsgCenterService(BT_DISCONNECTED_TO_MSGCENTER, 0, nullptr, 0); break; default: break; } } // 释放音频焦点 static void AudioDeactInterrupt(AudioStreamType type) { static_print_debug("[AudioDeactInterrupt] start type:0x%x, audioState:0x%x", type, g_audioState); if ((type == AUDIO_STREAM_VOICE_CALL_BT_SCO && g_audioState >= AUDIO_ACT_INTERRUPT_BT_SCO) || (type == AUDIO_STREAM_RING && g_audioState == AUDIO_ACT_INTERRUPT_WATCH_RING)) { TjdPhoneAudio::GetInstance().PhoneAudioManagerDeactInterrupt(); } } // 申请音频焦点 static void AudioActInterrupt(AudioStreamType type) { int ret = OHOS_SUCCESS; static_print_debug("[AudioActInterrupt] start type:0x%x, audioState:0x%x", type, g_audioState); if (type != AUDIO_STREAM_VOICE_CALL_BT_SCO && type != AUDIO_STREAM_RING) { static_print_error("[AudioActInterrupt] failed! type:0x%x, audioState:0x%x", type, g_audioState); return; } MUTEX_Lock(g_audioMutex); // 申请蓝牙通话焦点 if (type == AUDIO_STREAM_VOICE_CALL_BT_SCO && g_audioState < AUDIO_ACT_INTERRUPT_BT_SCO) { if (g_audioState == AUDIO_ACT_INTERRUPT_WATCH_RING) { AudioDeactInterrupt(AUDIO_STREAM_RING); } ret = TjdPhoneAudio::GetInstance().PhoneAudioManagerActInterrupt(type); if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_ACT_INTERRUPT_BT_SCO; } } else if (type == AUDIO_STREAM_RING && g_audioState < AUDIO_ACT_INTERRUPT_WATCH_RING) { ret = TjdPhoneAudio::GetInstance().PhoneAudioManagerActInterrupt(type); if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_ACT_INTERRUPT_WATCH_RING; } } if (ret != OHOS_SUCCESS) { static_print_error("[AudioActInterrupt] failed! type:0x%x, audioState:0x%x", type, g_audioState); } MUTEX_Unlock(g_audioMutex); } // 媒体连接SCO设备 static void AudioConnectScoDevInit(void) { int ret; TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); static_print_debug("[AudioConnectScoDevInit] start scoFlag:0x%x, audioState:0x%x", g_scoFlag, g_audioState); if (g_scoFlag != HFP_SCO_STATE_CONNECTED || g_audioState < AUDIO_ACT_INTERRUPT_BT_SCO) { return; } MUTEX_Lock(g_audioMutex); if (g_audioState < AUDIO_STREAM_INIT) { if (g_audioState < AUDIO_CONN_IN_BT_SCO) { // 配置媒体连接SCO设配状态(下行),只有在SCO连接后才能设置 ret = audio.PhoneAudioManagerSetDeviceConnState(IN_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED); if (ret != OHOS_SUCCESS) { static_print_error("[AudioConnectScoDevInit] sco in ret:%d", ret); MUTEX_Unlock(g_audioMutex); return; } else { g_audioState = AUDIO_CONN_IN_BT_SCO; } } if (g_audioState < AUDIO_CONN_OUT_BT_SCO) { // 配置媒体连接SCO设配状态(上行),只有在SCO连接后才能设置 ret = audio.PhoneAudioManagerSetDeviceConnState(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_CONNECTED); if (ret != OHOS_SUCCESS) { static_print_error("[AudioConnectScoDevInit] sco out ret:%d", ret); MUTEX_Unlock(g_audioMutex); return; } else { g_audioState = AUDIO_CONN_OUT_BT_SCO; } } if (g_hdlUpSco == INVALID_PHONE_SERVICE_VALUE) { g_hdlUpSco = audio.PhoneAudioStreamOutInit(AUDIO_UP_LINK); } if (g_hdlDnSco == INVALID_PHONE_SERVICE_VALUE) { g_hdlDnSco = audio.PhoneAudioStreamInInit(AUDIO_DOWN_LINK); } if (g_hdlUpSco != INVALID_PHONE_SERVICE_VALUE && g_hdlDnSco != INVALID_PHONE_SERVICE_VALUE) { g_audioState = AUDIO_STREAM_INIT; } } static_print_debug("[AudioConnectScoDevInit] end audioState:%d, hdlUpSco:%d, hdlDnSco:%d", g_audioState, g_hdlUpSco, g_hdlDnSco); MUTEX_Unlock(g_audioMutex); } // 建立上行通路 static void AudioUpStart(void) { int ret = OHOS_SUCCESS; TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); uint32 micShmId = 0; static_print_debug("[AudioUpStart] start scoFlag:%d, audioState:%d", g_scoFlag, g_audioState); if (g_scoFlag != HFP_SCO_STATE_CONNECTED || g_audioState < AUDIO_STREAM_INIT) { return; } MUTEX_Lock(g_audioMutex); if (g_audioState < AUDIO_STREAM_START_UP) { if (g_hdlUpMic == INVALID_PHONE_SERVICE_VALUE) { g_hdlUpMic = audio.PhoneAudioStreamInInit(AUDIO_UP_LINK); } if (g_audioState < AUDIO_STREAM_START_SCO) { ret = audio.PhoneAudioStreamInStart(g_hdlDnSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpStart] dn_sco ret:%d", ret); } ret |= audio.PhoneAudioStreamOutStart(g_hdlUpSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpStart] up_sco ret:%d", ret); } if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_STREAM_START_SCO; } } ret |= audio.PhoneAudioStreamInStart(g_hdlUpMic); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpStart] up_mic ret:%d", ret); } ret |= audio.PhoneAudioStreamInGetChannelId(g_hdlUpMic, &micShmId); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpStart] up_mic shm ret:%d", ret); } ret |= audio.PhoneAudioStreamOutAttachFrontend(g_hdlUpSco, micShmId); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpStart] up_sco attach ret:%d", ret); } if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_STREAM_START_UP; } } static_print_debug("[AudioUpStart] end audioState:%d, hdlUpMic:%d, hdlUpSco:%d, micShmId:0x%x", g_audioState, g_hdlUpMic, g_hdlUpSco, micShmId); MUTEX_Unlock(g_audioMutex); } // 建立下行通路 static void AudioDnStart(void) { int ret = OHOS_SUCCESS; TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); uint32 spkShmId = 0; static_print_debug("[AudioDnStart] start scoFlag:%d, audioState:%d", g_scoFlag, g_audioState); if (g_scoFlag != HFP_SCO_STATE_CONNECTED || g_audioState < AUDIO_STREAM_INIT) { return; } MUTEX_Lock(g_audioMutex); if (g_audioState < AUDIO_STREAM_START_DN) { if (g_hdlDnSpk == INVALID_PHONE_SERVICE_VALUE) { g_hdlDnSpk = audio.PhoneAudioStreamOutInit(AUDIO_DOWN_LINK); } if (g_audioState < AUDIO_STREAM_START_SCO) { ret = audio.PhoneAudioStreamOutStart(g_hdlUpSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnStart] up_sco ret:%d", ret); } ret |= audio.PhoneAudioStreamInStart(g_hdlDnSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnStart] dn_sco ret:%d", ret); } if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_STREAM_START_SCO; } } ret |= audio.PhoneAudioStreamOutStart(g_hdlDnSpk); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnStart] dn_spk ret:%d", ret); } ret |= audio.PhoneAudioStreamOutGetChannelId(g_hdlDnSpk, &spkShmId); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnStart] dn_spk shm ret:%d", ret); } ret |= audio.PhoneAudioStreamInAttachBackend(g_hdlDnSco, spkShmId); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnStart] dn_sco attach ret:%d", ret); } if (ret == OHOS_SUCCESS) { g_audioState = AUDIO_STREAM_START_DN; } } static_print_debug("[AudioDnStart] end audioState:%d, hdlDnSpk:%d, hdlDnSco:%d, spkShmId:0x%x", g_audioState, g_hdlDnSpk, g_hdlDnSco, spkShmId); MUTEX_Unlock(g_audioMutex); } // 同步音量 static void SyncVolume(void) { unsigned char volume; volume = GetHFPCallCurrVolume(); SetHFPSpeakerVolume(volume); } // 蓝牙通话上行 static void AudioUp(void) { // 申请蓝牙通话音频焦点 AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_BT_SCO); // 媒体连接SCO设备 AudioConnectScoDevInit(); // 建立音频上行通路 AudioUpStart(); static_print_debug("[AudioUp] audioState:%d", g_audioState); } // 蓝牙通话下行 static void AudioDn(void) { AudioActInterrupt(AUDIO_STREAM_VOICE_CALL_BT_SCO); // 媒体连接SCO设备 AudioConnectScoDevInit(); // 建立音频下行通路 AudioDnStart(); if (g_audioState == AUDIO_STREAM_START_DN) { // 同步音量 SyncVolume(); } static_print_debug("[AudioDn] audioState:%d", g_audioState); } static void AudioSetup(void) { if (g_audioState < AUDIO_STREAM_START_DN) { AudioDn(); } if (g_audioState != AUDIO_STREAM_START_UP) { AudioUp(); } } static void PlayWatchRing(void) { static_print_debug("[PlayWatchRing] start"); } static void AudioUpRelease(void) { int ret; TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); if (g_hdlUpSco != INVALID_PHONE_SERVICE_VALUE) { ret = audio.PhoneAudioStreamOutStop(g_hdlUpSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpRelease] [OutStop] hdlUpSco ret:%d", ret); } ret = audio.PhoneAudioStreamOutDeinit(g_hdlUpSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpRelease] [OutDeinit] hdlUpSco ret:%d", ret); } } if (g_hdlUpMic != INVALID_PHONE_SERVICE_VALUE) { ret = audio.PhoneAudioStreamInStop(g_hdlUpMic); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] [InStop] hdlUpMic ret:%d", ret); } ret = audio.PhoneAudioStreamInDeinit(g_hdlUpMic); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] [InDeinit] hdlUpMic ret:%d", ret); } } if (g_audioState >= AUDIO_CONN_OUT_BT_SCO) { ret = audio.PhoneAudioManagerSetDeviceConnState(OUT_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] sco out ret:%d", ret); } } g_hdlUpSco = INVALID_PHONE_SERVICE_VALUE; g_hdlUpMic = INVALID_PHONE_SERVICE_VALUE; } static void AudioDnRelease(void) { int ret; TjdPhoneAudio &audio = TjdPhoneAudio::GetInstance(); if (g_hdlDnSco != INVALID_PHONE_SERVICE_VALUE) { ret = audio.PhoneAudioStreamInStop(g_hdlDnSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpRelease] [InStop] hdlDnSco ret:%d", ret); } ret = audio.PhoneAudioStreamInDeinit(g_hdlDnSco); if (ret != OHOS_SUCCESS) { static_print_error("[AudioUpRelease] [InDeinit] hdlDnSco ret:%d", ret); } } if (g_hdlDnSpk != INVALID_PHONE_SERVICE_VALUE) { ret = audio.PhoneAudioStreamOutStop(g_hdlDnSpk); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] [OutStop] hdlDnSpk ret:%d", ret); } ret = audio.PhoneAudioStreamOutDeinit(g_hdlDnSpk); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] [OutDeinit] hdlDnSpk ret:%d", ret); } } if (g_audioState >= AUDIO_CONN_IN_BT_SCO) { ret = audio.PhoneAudioManagerSetDeviceConnState(IN_BLUETOOTH_SCO, AUDIO_DEVICE_DISCONNECTED); if (ret != OHOS_SUCCESS) { static_print_error("[AudioDnRelease] sco in ret:%d", ret); } } g_hdlDnSco = INVALID_PHONE_SERVICE_VALUE; g_hdlDnSpk = INVALID_PHONE_SERVICE_VALUE; } /* 销毁上下行通路 释放音频焦点 */ void AudioRelease(void) { if (g_audioState == AUDIO_UNKNOW) { return; } MUTEX_Lock(g_audioMutex); AudioUpRelease(); AudioDnRelease(); /* 释放音频焦点 */ AudioDeactInterrupt(AUDIO_STREAM_VOICE_CALL_BT_SCO); AudioDeactInterrupt(AUDIO_STREAM_RING); // 适配某些机型不触发SCO g_audioState = AUDIO_UNKNOW; static_print_debug("[AudioRelease] audioState:%d,", g_audioState); MUTEX_Unlock(g_audioMutex); } // SCO连接处理 static void ScoConnectPro(void) { // 通知sco建立连接(或通话转移:手机 -> 手表) ScoStatusCb(HFP_SCO_STATE_CONNECTED); if (g_currCallState == HFP_HF_CALL_STATE_ACTIVE && g_scoFlag == HFP_SCO_STATE_CONNECTED) { // The call is transferred from the phone to the watch. Need to show the call notification view. hfp_hf_calls_info_t call = {}; HfpIncomingEventPublish(TOPIC_EVENT_HFP_PHONE_TO_WATCH, call); } PostGraphicEvent(AudioSetup); } // SCO断连处理 static void ScoDisconnectPro(void) { static_print_debug("[ScoDisconnectPro] start CallState:%d", g_currCallState); ScoStatusCb(HFP_SCO_STATE_DISCONNECTED); if (g_currCallState == HFP_HF_CALL_STATE_ACTIVE && g_scoFlag == HFP_SCO_STATE_DISCONNECTED) { // The call is transferred from the watch to the phone. Need to close the call notification view. hfp_hf_calls_info_t call = {}; HfpIncomingEventPublish(TOPIC_EVENT_HFP_WATCH_TO_PHONE, call); } AudioRelease(); // 为了保持时序,此处采取同步调用 usleep(5000); // 增加延时确保SCO断开AUDIO通路释放成功 } // Sco连接状态变化回调函数,音频连接状态 static void ScoStateChanged(const bd_addr_t *bdAddr, hfp_sco_connect_state_t state) { g_scoFlag = state; static_print_debug("[ScoStateChanged] hfpState:%d, ScoFlag:%d, CallNum:%d", state, g_scoFlag, g_currCallNum); switch (state) { case HFP_SCO_STATE_CONNECTING: PhoneServiceScreenCtr(1); if (g_scoFlag != HFP_SCO_STATE_CONNECTED) { g_scoFlag = HFP_SCO_STATE_CONNECTED; CopyBdAddr(bdAddr); ScoConnectPro(); static_print_debug("[ScoStateChanged] SCO connecting!"); } break; case HFP_SCO_STATE_CONNECTED: static_print_debug("[ScoStateChanged] SCO connected!"); break; case HFP_SCO_STATE_DISCONNECTING: static_print_debug("[ScoStateChanged] SCO disconnecting!"); break; case HFP_SCO_STATE_DISCONNECTED: static_print_debug("[ScoStateChanged] SCO disconnected!"); ScoDisconnectPro(); PhoneServiceScreenCtr(0); break; default: break; } } static void HfpBatteryChanged(const bd_addr_t *bdAddr, int batteryLevel) { UNUSED(bdAddr); UNUSED(batteryLevel); static_print_debug("[HfpBatteryChanged] batteryLevel:%d", batteryLevel); } static void HfpSignalStrengthChanged(const bd_addr_t *bdAddr, int signalStrength) { UNUSED(bdAddr); UNUSED(signalStrength); static_print_debug("[HfpSignalStrengthChanged] signalStrength:%d", signalStrength); } static void HfpRegistStatusChanged(const bd_addr_t *bdAddr, int status) { UNUSED(bdAddr); UNUSED(status); static_print_debug("[HfpRegistStatusChanged] status:%d", status); } static void HfpRoamingStatusChanged(const bd_addr_t *bdAddr, int status) { UNUSED(bdAddr); UNUSED(status); static_print_debug("[HfpRoamingStatusChanged] status:%d", status); } static void HfpOperatorSelection(const bd_addr_t *bdAddr, unsigned char *name, unsigned int len) { UNUSED(bdAddr); UNUSED(name); UNUSED(len); static_print_debug("[HfpOperatorSelection] name: %s, len:%d", name, len); } static void HfpSubscriberNumber(const bd_addr_t *bdAddr, unsigned char *number, unsigned int len) { UNUSED(bdAddr); UNUSED(number); UNUSED(len); static_print_debug("[HfpSubscriberNumber] number: %s, len:%d", number, len); } static void VoiceRecogStatusChanged(const bd_addr_t *bdAddr, int status) { UNUSED(bdAddr); UNUSED(status); static_print_debug("[VoiceRecogStatusChanged] status:%d", status); } static void InbandRingtoneChanged(const bd_addr_t *bdAddr, int status) { UNUSED(bdAddr); UNUSED(status); static_print_debug("[InbandRingtoneChanged] status:%d", status); } static void BtHfpVolumeChanged(int volumeType, unsigned char hfpVolume) { // mic if (volumeType == HFP_VOLUME_MIC) { static_print_debug("VolumeChanged Type:%d, hfpVolume:%d", volumeType, hfpVolume); } // speak if (volumeType == HFP_VOLUME_SPEAKER) { int32_t minVolume = TjdPhoneAudio::GetInstance().PhoneAudioGetMinVolume(); int32_t maxVolume = TjdPhoneAudio::GetInstance().PhoneAudioGetMaxVolume(); int32_t volume = hfpVolume * (maxVolume - minVolume) / CALL_VOLUME_MAX; // 转换 volume = (volume == 0) ? ((maxVolume - minVolume) / CALL_VOLUME_MAX) : volume; bool ret = TjdPhoneAudio::GetInstance().PhoneAudioSetVolume(volume); if (!ret) { static_print_error("VolumeChanged Type:%d, ret:%d", volumeType, ret); } static_print_debug("VolumeChanged Type:%d, min:%d, max:%d volume:%d ret:%d", volumeType, minVolume, maxVolume, volume, ret); } } // 音量调节回调 static void VolumeChanged(const bd_addr_t *bdAddr, hfp_volume_type_t type, unsigned char volume) { UNUSED(bdAddr); static_print_debug("[VolumeChanged] type:%d volume:%d", type, volume); GraphicService::GetInstance()->PostGraphicEvent(std::bind(BtHfpVolumeChanged, type, volume)); } // 设置完整通话标志 static void SetCompleteCallFlag(const hfp_hf_calls_info_t *call) { if (call->state == HFP_HF_CALL_STATE_INCOMING) { // 呼入 g_completeCallFlag = true; } else if ((call->state == HFP_HF_CALL_STATE_DIALING || call->state == HFP_HF_CALL_STATE_ALERTING) && (g_currCallNum == 1 || g_currCallNum == 0)) // 正在拨号或对方响铃 { g_completeCallFlag = true; } else if (call->state == HFP_HF_CALL_STATE_ACTIVE) { // 正在通话 g_completeCallFlag = true; } } static void CallAudioHandle(const hfp_hf_calls_info_t *call) { int state = call->state; if (state == HFP_HF_CALL_STATE_INCOMING || state == HFP_HF_CALL_STATE_DIALING || state == HFP_HF_CALL_STATE_ALERTING) { // 电话呼入,支持播放手机铃声 if (call->in_band_ring) { // 播放手机端铃声 PostGraphicEvent(AudioDn); } else { if (g_scoFlag != HFP_SCO_STATE_CONNECTED) { // 播放手表铃声 PostGraphicEvent(PlayWatchRing); } } } else if (state == HFP_HF_CALL_STATE_FINISHED) { return; } else if (g_scoFlag == HFP_SCO_STATE_CONNECTED) { PostGraphicEvent(AudioSetup); } } static void CallShakeHandle(const hfp_hf_calls_info_t *call) { int state = call->state; static_print_debug("[CallShakeHandle] state:%d", state); if (state == HFP_HF_CALL_STATE_INCOMING) { // 电话呼入,支持播放手机铃声 TJD::TjdUiSettingCenter::GetInstance().PhoneShakeEvent(); } else if (state == HFP_HF_CALL_STATE_FINISHED || state == HFP_HF_CALL_STATE_ACTIVE) { TJD::TjdUiSettingCenter::GetInstance().ShakeEndEvent(); } } // 通话状态变化上报回调 static void CallStateChanged(const bd_addr_t *bdAddr, const hfp_hf_calls_info_t *call) { CopyBdAddr(bdAddr); if (call == nullptr || g_btConnState != PROFILE_STATE_CONNECTED) { static_print_error("call is null or BT disconnected connStatus: 0x%X", g_btConnState); return; } SetCompleteCallFlag(call); CallAudioHandle(call); CallShakeHandle(call); static_print_debug("CallStateChanged state:%d", call->state); switch (call->state) { case HFP_HF_CALL_STATE_ACTIVE: // 0正在通话 CallChangeActivePro(call); break; case HFP_HF_CALL_STATE_HELD: // 挂起 CallChangeHeldPro(call); break; case HFP_HF_CALL_STATE_DIALING: // 2呼出,正在拨号 PhoneServiceScreenCtr(1); CallChangeDialPro(call); break; case HFP_HF_CALL_STATE_ALERTING: // 3呼出,对方响铃 PhoneServiceScreenCtr(1); CallChangeAlertPro(call); break; case HFP_HF_CALL_STATE_INCOMING: // 呼入 PhoneServiceScreenCtr(1); CallChangeIncomePro(call); break; case HFP_HF_CALL_STATE_WAITING: // 呼入等待 PhoneServiceScreenCtr(1); CallChangeIncomePro(call); break; case HFP_HF_CALL_STATE_FINISHED: // 7拒接/结束电话 CallChangeFinishPro(call); PhoneServiceScreenCtr(0); break; default: break; } // 规避某些型号手机在电话呼入时重复断开和连接SCO if (call->state == HFP_HF_CALL_STATE_FINISHED) { if (g_currCallNum == 0) { g_currCallState = HFP_HF_CALL_STATE_FINISHED; } } else { g_currCallState = call->state; } if (g_currCallNum == 0) { g_completeCallFlag = false; } } // 拨号失败回调 static void DialErrorCode(const bd_addr_t *bdAddr, int code) { UNUSED(bdAddr); static_print_debug("[DialErrorCode] code:%d", code); PhoneServiceErrorCallback(ERROR_DIAL, code); } static void CodecChanged(const bd_addr_t *bdAddr, int codec) { UNUSED(bdAddr); if (codec == HFP_HF_CODEC_ID_CVSD) { g_call_codec = PCM; } else if (codec == HFP_HF_CODEC_ID_MSBC) { g_call_codec = mSBC; } static_print_debug("[CodecChanged] codec:%d, call_codec:%d", codec, g_call_codec); } static void RegisterHfpHfCallbacks(void) { static_print_debug("[RegisterHfpHfCallbacks]"); int ret; hfp_hf_callbacks_t callbacks = { ConnStateChanged, ScoStateChanged, HfpBatteryChanged, HfpSignalStrengthChanged, HfpRegistStatusChanged, HfpRoamingStatusChanged, HfpOperatorSelection, HfpSubscriberNumber, VoiceRecogStatusChanged, InbandRingtoneChanged, VolumeChanged, CallStateChanged, DialErrorCode, CodecChanged, }; ret = hfp_hf_register_callbacks(&callbacks); if (ret != 0) { static_print_error("[RegisterHfpHfCallbacks] ret:%d", ret); } } static void ContactsSyncEvent() { ContactsGetCase(); } void TjdPhoneServiceInit(void) { static_print_debug("[PhoneServiceInit] start"); g_scoFlag = HFP_SCO_STATE_DISCONNECTED; int32_t ret = TjdPhoneAudio::GetInstance().AudioInit(); if (ret != OHOS_SUCCESS) { static_print_error("[AudioInit] failed!"); } g_audioMutex = MUTEX_InitValue(); DIR *dir = nullptr; dir = opendir(TJD_CALL_LOG_DIR); if (dir == nullptr) { mkdir(TJD_CALL_LOG_DIR, S_IREAD | S_IWRITE); } else { closedir(dir); } if (GetCallLogFileSize() == OHOS_FAILURE) { // 如果不存在文件,创建新文件 (void)ClearCallLogInfoFile(); } (void)memset_s(g_bdAddr.addr, BD_ADDR_LEN, 0, BD_ADDR_LEN); CallListInit(); ContactsGetCase(); tjd_service_bt_register_contacts_event(ContactsSyncEvent); RegisterHfpHfCallbacks(); static_print_debug("[PhoneServiceInit] end"); } uint32_t GetCallAudioCodec(void) { return g_call_codec; }