蓝牙电话之HFP-通话

news/2024/10/18 9:19:56/

蓝牙电话之HFP-通话

文章《蓝牙电话之HFP-连接》里已经对HFP的连接进行了简单分析,这篇主要和大家探讨下通话场景下的相关操作,如拨打、接听、挂断电话(AG侧、HF侧)、切换声道这几个场景。

蓝牙通话中主要涉及到以下两个方面的关注点:获取当前的通话状态和传送通话声音,这两个关注点直接决定了蓝牙电话应用是否能正常工作。

获取当前的通话状态:主要通过AT命令“+CIEV”和“+CLCC”来获取AG侧的通话状态和信息,HF侧不管如何操作都要以AG侧的状态为准。

+CIEV命令的定义如下:
在这里插入图片描述

该指令是AG侧主动将通话状态更新到HF侧的,依赖于“AT+CMER”来打开AG侧的更新标志位
在这里插入图片描述
从+CIEV命令的定义不难看出,和所对应的的值都在“AT+CIND=?”命令中定义清楚的,感兴趣的同学可以自行查看。通话中以下三个indicator需要重点关注
在这里插入图片描述dicator对应值的含义分别是:

callsetup:电话建立过程,值为2

call:通话成功,值为1

callheld:电话保持的过程,值为7

value对应的值的含义如图所示:
在这里插入图片描述
这样ind + value的不同组合就可以代表不同的电话场景流程。

+CLCC命令的定义如下:
在这里插入图片描述

该指令需要HF侧主动通过“AT+CLCC”指令告知AG侧将当前的电话信息通过“+CLCC”发送过来。接收到“+CLCC”指令,HF侧就可以知道当前的电话状态和号码等关键信息。

传送通话声音:蓝牙电话应用最根本的目的是传输双方的通话声音,既要将远端的输入语音经本端手机的电话模块接收到后再通过蓝牙模块AG侧传送到HF侧播放出来,也要将本端的输出语音通过HF侧传送到AG侧,再通过本端手机的电话模块发送出去。传输通话音频的通道主要是通话链路也就是大家平常说的SCO或eSCO链路。

SCO或eSCO的建立依赖于HFP协议的Service Level Connection连接成功(详情请参考《蓝牙电话之HFP-连接》),再通过HCI命令建立通话音频链路。

音频链路当前有两种编码方式,分别为CVSD和mSBC。采用哪种编码方式是有建立连接的双方协商决定的,AT命令“+BRSF”中HF和AG双方会分别发送自己支持的features给对方,如果双方都支持编码协商即标志位Codec Negotiation,HF侧主动通过“AT+BAC”的AT命令告知AG侧两种编码方式的编号分别为:1-CVSD,2-mSBC,并且在建立音频链路时多采用mSBC的编码方式,否则都是CVSD编码。

音频链路连接对应的HCI命令为:Setup Synchronous Connection Command,如果本端Controller支持Enhanced Setup Synchronous Connection指令(详情请查看Read Local Supported Commands Command的HCI命令),则创建连接的HCI命令为:Enhanced Setup Synchronous Connection Command

两种创建音频链路的HCI为:
在这里插入图片描述
在这里插入图片描述

音频链路SCO或eSCO建立成功后,通话语音就能在AG、HF两侧正常传输了。

以上就是蓝牙电话通话中需要了解的最重要的两点,HF侧的上层蓝牙电话应用只需监听BluetoothHeadsetClient中定义的如下两个广播就可以执行上层逻辑。

    /*** Intent sent whenever state of a call changes.** <p>It includes:* {@link #EXTRA_CALL},* with value of {@link BluetoothHeadsetClientCall} instance,* representing actual call state.</p>*/public static final String ACTION_CALL_CHANGED ="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED"; 
    /*** Intent sent whenever audio state changes.** <p>It includes two mandatory extras:* {@link BluetoothProfile#EXTRA_STATE},* {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},* with possible values:* {@link #STATE_AUDIO_CONNECTING},* {@link #STATE_AUDIO_CONNECTED},* {@link #STATE_AUDIO_DISCONNECTED}</p>* <p>When <code>EXTRA_STATE</code> is set* to </code>STATE_AUDIO_CONNECTED</code>,* it also includes {@link #EXTRA_AUDIO_WBS}* indicating wide band speech support.</p>*/public static final String ACTION_AUDIO_STATE_CHANGED ="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED";

接下来再详细分析下这两个广播是如何一步步发送出去的,见如下时序图。
在这里插入图片描述

下面以场景为视角简单分析上述两点在其中的作用及流程,编码方式都是mSBC。

1、 拨打电话-AG

拨打电话大体分为拨号、响铃、通话这三个部分,状态变化后AG侧都会主动通知HF侧,HF侧再通过“AT+CLCC”获取详细的电话参数信息。
在这里插入图片描述

2、 拨打电话-HF

HF侧的拨打电话和AG侧比较起来就多了一个步骤,通过AT命令“ATD”将需要拨打的电话信息发送到AG侧,然后通过手机的电话模块呼出电话。

蓝牙电话应用层调用BluetoothHeadsetClient.dial()后,只需监听相应广播即可。
在这里插入图片描述

3、 接听电话

来电接听这里还需要我们了解In-Band Ring来电响铃功能,该功能支持在来电时将手机上设置的响铃铃声通过蓝牙传送到HF侧,从而在设备端播出该铃声。AG在“BRSF”交互features时,如果In-Band Ring Tone Capability标志位设置成 true 则代表支持该功能,所以蓝牙电话应用根据自身的配置来进行取舍。

接听来电的方式就两种,手机上接听或车机来电提醒界面(车机语音控制)接听,这样的话HF侧的操作流程对比AG侧也就是多了步将接听的动作以AT命令“ATA”发送给手机执行接听流程。

车载端接听来电则蓝牙电话应用层调用BluetoothHeadsetClient.acceptCall()后监听相应广播即可。

HF侧接听来电-In-Band Ringing:
在这里插入图片描述

HF侧接听来电-No In-Band Ringing:

在这里插入图片描述

AG侧接听来电:
在这里插入图片描述

4、 挂断电话

电话挂断和接听来电类似,HF侧操作也是通过AT命令“AT+CHUP”将挂断电话操作告知AG侧,真正的电话挂断操作是有手机的电话模块来执行的。

蓝牙电话应用层只需要调用BluetoothHeadsetClient.terminateCall()完监听AG_CALL_CHANGE广播即可。
在这里插入图片描述

5、 切换声道

声道的切换就是通话语音从手机端切到车载端播放,或反之从车载端切到手机端播放。由于通话音频数据的传输是在SCO链路上进行的,所以建立SCO就代表通话语音切到车载端播放,断开SCO就代表通话语音切到手机上播放。

建立和断开SCO的操作双方都可以操作,从而HF侧的蓝牙电话应用只需关心BluetoothHeadsetClient中的connectAudio()和disconnectAudio()这两个接口就可实现上述功能。
在这里插入图片描述

蓝牙电话通话的相关分析大概就这样了,对此感兴趣的同学可以私信我一起探讨哦。

更多互联互通技术,欢迎关注微信公众号:Connectivity
在这里插入图片描述


http://www.ppmy.cn/news/462006.html

相关文章

如何在Android中使用Intent拨打电话?

本文翻译自&#xff1a;How to make a phone call using intent in Android? Im using the following code to make a call in Android but it is giving me security exception please help. 我正在使用以下代码在Android中拨打电话&#xff0c;但这给我带来了安全异常&#…

无法在Android手机上拨打或接听电话,如何解决

使用Android&#xff0c;拨打和接听电话变得更加容易。您可以在几分之一秒内与其他联系人建立联系。但是&#xff0c;一些用户在无法在Android手机上拨打或接听电话时不断抱怨这些情况。在这样的时刻&#xff0c;当你看到周围的每个人都忙于他们的智能手机&#xff0c;你甚至不…

android拨打电话无法跳转到通话界面

最近客户要求我们用谷歌的dialer替换原生的dialer,替换之后发现在拨打电话的时候无法跳转到指定的界面.通过阅读源码发现,telecom固定的了跳转的界面. packages/services/Telecomm/src/com/android/server/telecom/InCallController.java public InCallController(Context con…

python 实现手机自动拨打电话(通话压力测试)

现在能用自动化实现的&#xff0c;尽量使用自动化程序去操作&#xff0c;代替人工去操作&#xff0c;更有效率。 今天说下用python结合adb命令去实现安卓手机端的通话压力测试。 #操作前先在设置里打开power键可以结束通话按钮&#xff0c;否则会导致代码报错 from time impor…

Android如何判断手机是否处于正在通话中,通话状态的判断

1. 如何判断手机是否处于正在通话中&#xff1f;&#xff08;任何时候都可以判断手机是否处于通过中&#xff09; private boolean phoneIsInUse() { boolean phoneInUse false; try { ITelephony phone ITelephony.Stub.asInterface(ServiceManager.checkService("pho…

小米8android系统,小米8:2021年,是时候说再见了!

众所周知&#xff0c;一款安卓手机的使用周期大概是在2-3年。在这之后&#xff0c;很多用户都会选择更新换代。小米8&#xff0c;作为小米发布已经两年半的机型&#xff0c;现在也到了要和我们说再见的时候了。那么&#xff0c;作为小米曾经的数字旗舰&#xff0c;小米8还能不能…

小米8se怎么解屏幕锁_小米8 SE解锁system系统分区教程_小米8SE如何一键解锁系统分区...

下面也是咱们的这个小米8 SE手机解锁system系统分区的教程了&#xff0c;看到有不少的机友想对自己的手机解锁系统分区&#xff0c;可是不知道从哪里入手&#xff0c;这个解锁分区的教程看似复杂&#xff0c;其实也挺简单的&#xff0c;前提条件是你的手机已经进行过root操作了…

Android 8 WiFi断流,小米8wifi断流怎么解决

大家好&#xff0c;我是时间财富网智能客服时间君&#xff0c;上述问题将由我为大家进行解答。 小米8wifi断流解决的方法如下&#xff1a; 1、下拉手机通知栏&#xff0c;按住WiFi。 2、选取一个WiFi连接&#xff0c;点击设置。 3、点击WLAN&#xff0c;点击底部高级设置。 4、…