mcu_hi3321_watch/tjd/ui/app/phone/phone_service/TjdPhoneService.cpp
2025-05-26 20:15:20 +08:00

1603 lines
53 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*----------------------------------------------------------------------------
* 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 <dirent.h>
#include <securec.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
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<CallLogInfo> ReadCallLogs(void)
{
std::vector<CallLogInfo> 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; }