Android10.0(Q) 实现通话中播放音乐/通话背景音(答录机/魔音功能)

简介: Android10.0(Q) 实现通话中播放音乐/通话背景音(答录机/魔音功能)

前言


这个功能大体意思类似机器人交互的效果,一般多应用到客服接听场景中,电话接通自动播放一段录音给


对方听,根据选项操作录音解析等完成一整个流程。这里面电话接通播放声音给对方听普通应用是做不到的,


因为这关系到音频焦点分配的问题。Android 电话拨入音频焦点(Audio Focus)


谷歌默认的策略,当电话响铃或接通后,电话的音频焦点使用优先级是最高的,其它应用是无法抢占的。


但我们有源码啊,可以跳过这个地方,但是尝试后你会发现依旧不行。因为这还关系到 audio 驱动部分的上下行。


修改方案

frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerBGSPlayer.cpp
vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerTelephonyTx.cpp
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h

frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java


canReassignAudioFocus 直接放回 true,其实最终发现改不改这里无所谓,主要是 audio 的上下行

     private boolean canReassignAudioFocus() {
         // focus requests are rejected during a phone call or when the phone is ringing
         // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus
        /*if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) {
             return false;
         }*/
        return true;
     }


audio driver 部分需要修改 mPcmMixerDlGain 和 mPcmMixerUlGain 默认初始值


其中 mPcmMixerDlGain 表示下行 gain 值,影响的是本端听到的声音大小


mPcmMixerUlGain 表示上行 gain 值,影响的是对方听到的声音大小,默认值是 0x00,


所以对方听不到,只要将 mPcmMixerUlGain 改为非 0 值即可,最大值 0xFF


vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerBGSPlayer.cpp

 uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerDlGain = 0xFF;
-uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerUlGain = 0x0;
+uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerUlGain = 0xFF;
$ find -name "*.cpp" | xargs grep "setPcmMixerDlMute"
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerDlGain = 0xFF;
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:    pSpeechDriver->BGSoundConfig(mPcmMixerUlGain, mPcmMixerDlGain);
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:        mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:        mPcmMixerDlGain = 0xFF;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:uint8_t SpeechPcmMixerTelephonyTx::mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:    pSpeechDriver->TelephonyTxConfig(mPcmMixerUlGain, mPcmMixerDlGain);
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:        mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:        mPcmMixerDlGain = 0xFF;
$ find -name "*.cpp" | xargs grep "setPcmMixerDlMute("
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:void SpeechPcmMixerBGSPlayer::setPcmMixerDlMute(const bool mute_on) {
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:void SpeechPcmMixerTelephonyTx::setPcmMixerDlMute(const bool mute_on) {
./common/V3/aud_drv/AudioALSAHardware.cpp:        SpeechPcmMixerBGSPlayer::setPcmMixerDlMute((bool)value);


AndroidO 版本修改方法


frameworks/base/media/java/android/media/AudioAttributes.java
frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSAStreamManager.cpp
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h

frameworks/base/media/java/android/media/AudioAttributes.java

         public Builder setCapturePreset(int preset) {
             switch (preset) {
+             case MediaRecorder.AudioSource.VOICE_UPLINK:
+             case MediaRecorder.AudioSource.VOICE_DOWNLINK:
+             case MediaRecorder.AudioSource.VOICE_CALL:
+             case MediaRecorder.AudioSource.REMOTE_SUBMIX:
                 case MediaRecorder.AudioSource.DEFAULT:
                 case MediaRecorder.AudioSource.MIC:

frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java

     private boolean canReassignAudioFocus() {
         // focus requests are rejected during a phone call or when the phone is ringing
         // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus
        /*if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) {
             return false;
         }*/
-        return true;
     }

vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSAStreamManager.cpp

AudioALSAStreamManager::AudioALSAStreamManager() :
     mForceDisableVoiceWakeUpForSetMode(false),
     mBypassPostProcessDL(false),
     mBGSDlGain(0xFF),
-    mBGSUlGain(0),
+    //mBGSUlGain(0),
+    mBGSUlGain(0xFF),
     mBypassDualMICProcessUL(false),


vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h

 #define HW_DIGITAL_GAIN_MAX (252)
 #define HW_DIGITAL_GAIN_STEP (4)   // 2==> 0.5 dB ,4==>1dB
-#define AUDIO_SYSTEM_UL_GAIN_MAX            (45)
+#define AUDIO_SYSTEM_UL_GAIN_MAX            (160)
 #define MIN_PGA_GAIN                                         (0)
 #define MAX_PGA_GAIN_RANGE                          (30)
 #define AUDIO_UL_PGA_STEP

vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h

 #define HW_DIGITAL_GAIN_MAX (252)
 #define HW_DIGITAL_GAIN_STEP (4)   // 2==> 0.5 dB ,4==>1dB
-#define AUDIO_SYSTEM_UL_GAIN_MAX            (45)
+#define AUDIO_SYSTEM_UL_GAIN_MAX            (160)
 #define MIN_PGA_GAIN                                         (2)
 #define MAX_PGA_GAIN_RANGE                          (30)
 #define AUDIO_UL_PGA_STEP  


其它问题收录


1、使用答录机的时候会听到连续的啪的声音


主要原因在于 AFE 不断去重新设置 uplink 的 AGC 那个寄存器。修正方法是当 mic volume

不变的时候不再重复设置 AGC 的那个寄存器。

Patch id: MAUI_02602310


2、答录机中进入远程访问之后,直接开始播放所有未读留言,此时用户输入 DTMF 无效


主要原因是函数 mmi_autoam_key_detection_callback 中没有把 MMI_AUTOAM_STATE_REMOTE_PRE_PLAY_UNREAD


这种 case 考虑进去,导致无法相对应的 DTMF 输入,修改方法是将这种 case 加进去


Patch id: MAUI_02029196


3、实现第三方的魔音功能的时候要修改 wav.c


添加第三方的魔音功能的时候,常常会要求开发 wav.c,因为要改到这里面的某些函数。出于策略,从 09A0924 之后,wav.c 等相关文件都被封装到 lib 中了,这部分将不会再重新开放出来。事实上,要实现魔音功能,其实不开放

wav.c 也是可以完成的,基本上只需要修改函数 wavADPCMPutData 和 wavDviADPCMPutDataMono,可以在 code

中对 ihdl->wav.Wav_PutData 进行赋值的地方进行相应的修改,赋值成自行修改之后的函数

wavADPCMPutData_modified 和 wavDviADPCMPutDataMono_modified 即可。


4、在通话中,播放背景音时,如何屏蔽掉按键音


如果是本地产生的按键音,可以利用 BGSND 的接口,把整个 speech 关闭。


修改 aud_snd_play_req 和 aud_snd_set_volume_req_hdlr:


SND_ConfigULMixer(snd_handle, KAL_TRUE, volume);


改为


SND_ConfigULMixer(snd_handle, KAL_FALSE, volume);


如果是因为按键产生 DTMF 发送到对方触发对方手机产生的声音,只能通过屏蔽本地产生 DTMF 处理。


方法是在通话时进入 option 选择其中的 DTMF 菜单并设成 off 或者直接在代码里设置


g_ucm_p->call_miss.is_dtmf=false 来实现。


5、来电时播放一段声音对对方听,自己这边不放出声来,同时本地的声音对方也听不见。然后在播放结束之后进入正常通话状态


修改文件 Am.c 中的函数 AM_SpeechOn()


在改函数内部加上判断条件,如果处于播放背景音的应用则不调用


AFE_TurnOnSpeaker(L1SP_SPEECH);


AFE_TurnOnMicrophone(L1SP_SPEECH);


在播放背景音的 callback 中调用函数


AFE_TurnOnSpeaker(L1SP_SPEECH);


AFE_TurnOnMicrophone(L1SP_SPEECH); 即可进入正常通话状态


参考


Android10.0AudioFocus之源码分析(二)


Android 电话拨入音频焦点(Audio Focus)


Android ALSA音频系统架构分析(1)----从Loopback了解Audio


Android 如何在通话中播放音乐/通话背景音


mt6735 Audio Common 通话时如何播放声音给对方听

目录
相关文章
|
2月前
|
Android开发
Android开发表情emoji功能开发
本文介绍了一种在Android应用中实现emoji表情功能的方法,通过将图片与表情字符对应,实现在`TextView`中的正常显示。示例代码展示了如何使用自定义适配器加载emoji表情,并在编辑框中输入或删除表情。项目包含完整的源码结构,可作为开发参考。视频演示和源码详情见文章内链接。
76 4
Android开发表情emoji功能开发
|
2月前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
56 3
|
4月前
|
编解码 测试技术 Android开发
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
本文详细介绍了如何利用CameraX库实现高质量的照片及视频拍摄功能,包括添加依赖、初始化、权限请求、配置预览与捕获等关键步骤。此外,还特别针对不同分辨率和帧率的视频拍摄提供了性能优化策略,确保应用既高效又稳定。
444 1
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
|
3月前
|
Web App开发 网络协议 Android开发
Android平台一对一音视频通话方案大比拼:WebRTC VS RTMP VS RTSP,谁才是王者?
【9月更文挑战第4天】本文详细对比了在Android平台上实现一对一音视频通话时常用的WebRTC、RTMP及RTSP三种技术方案。从技术原理、性能表现与开发难度等方面进行了深入分析,并提供了示例代码。WebRTC适合追求低延迟和高质量的场景,但开发成本较高;RTMP和RTSP则在简化开发流程的同时仍能保持较好的传输效果,适用于不同需求的应用场景。
195 1
|
3月前
|
Android开发 开发者
Android平台无纸化同屏如何实现实时录像功能
Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。
|
4月前
|
图形学 Android开发
小功能⭐️Unity调用Android常用事件
小功能⭐️Unity调用Android常用事件
|
6月前
|
数据库 Android开发 数据安全/隐私保护
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
281 2
|
6月前
|
Android开发
Android中如何快速的实现RecycleView的拖动重排序功能
使用`ItemTouchHelper`和自定义`Callback`,在`RecyclerView`中实现拖动排序功能。定义`ItemTouchHelperAdapter`接口,`Adapter`实现它以处理`onItemMove`方法。`SimpleItemTouchHelperCallback`设置拖动标志,如`LEFT`或`RIGHT`(水平拖动),并绑定到`RecyclerView`以启用拖动。完成这些步骤后,即可实现拖放排序。关注公众号“AntDream”获取更多内容。
126 3
|
7月前
|
移动开发 监控 Android开发
构建高效Android应用:从内存优化到电池寿命代码之美:从功能实现到艺术创作
【5月更文挑战第28天】 在移动开发领域,特别是针对Android系统,性能优化始终是关键议题之一。本文深入探讨了如何通过细致的内存管理和电池使用策略,提升Android应用的运行效率和用户体验。文章不仅涵盖了现代Android设备上常见的内存泄漏问题,还提出了有效的解决方案,包括代码级优化和使用工具进行诊断。同时,文中也详细阐述了如何通过减少不必要的后台服务、合理管理设备唤醒锁以及优化网络调用等手段延长应用的电池续航时间。这些方法和技术旨在帮助开发者构建更加健壮、高效的Android应用程序。
|
7月前
|
Android开发 数据安全/隐私保护 iOS开发
ios和安卓测试包发布网站http://fir.im的注册与常用功能
ios和安卓测试包发布网站http://fir.im的注册与常用功能
330 0
ios和安卓测试包发布网站http://fir.im的注册与常用功能