是否可以动态链接到 libcs​​d-client.so 以在 Galaxy S4 I9505 上启用通话录音

Posted

技术标签:

【中文标题】是否可以动态链接到 libcs​​d-client.so 以在 Galaxy S4 I9505 上启用通话录音【英文标题】:is it possible to dynamic link to libcsd-client.so to enable in call voice recording on Galaxy S4 I9505 【发布时间】:2013-05-28 20:19:19 【问题描述】:

I9505 在 APQ8064T 上运行,与上一代 MSM8960 相比,HAL 层在芯片组上设置通话录音音频路径的方式发生了变化。现在,除了在 Kernel 中设置正确的 Mixer 控件外,还需要通过 libcs​​d-client.so(Qualcomm 专有,封闭源代码)库向基带调制解调器发送某种“魔术”命令。

Google 通过 dlsym libcs​​d-client.so(请参阅csd_start_record 函数)在 HAL 层为 Nexus 4(运行 APQ8064)执行此操作。但是,在应用程序级别使用带有 MediaRecorder.Audiosource.VOICE_DOWNLINK 的 AudioRecord API 将不起作用,因为AudioPolicyManagerBase.cpp 已被硬编码为仅在通话中录音时接收带有通道掩码“AUDIO_CHANNEL_IN_MONO”或“AUDIO_CHANNEL_IN_STEREO”的 IOProfile用例,使用的通道掩码必须是 AUDIO_CHANNEL_IN_VOICE_UPLINK 或 AUDIO_CHANNEL_IN_VOICE_DNLINK。谷歌和三星似乎都无意纠正这个问题。奇怪的是,用于记录通话的公共 android API 永远不能保证正常工作。

因此,为了克服这个问题,我决定编写一个 NDK 可执行文件来对 csd_start_recording/csd_stop_recording 进行 dlsym,就像 Google 为 Nexus 4 所做的那样,并使用 amix/arec 实用程序在有根设备上进行本地录制。但现在问题来了。

在我的可执行文件中,我调用了 csd_client_init 和 csd_start_record,两个调用都没有返回错误,但是 logcat 显示来自 libcs​​d-client.so 的一些 QMI(Qualcomm MSM 接口)错误,并且记录的波形文件只有静音。有没有人尝试过类似的事情?我现在完全不知道如何在无需将修改后的 ROM 闪存到设备的情况下进行通话录音。

更新

我再次重复测试,但 QMI 错误似乎消失了。我猜我上次遇到的 QMI 错误是由于我在测试期间弄乱了机器的状态。但是,录制仍然不起作用。结果仍然只是沉默。下面是我通过“csd” grep 的 logcat 输出:

D/        (  217): csd_client_disable_device: rx 7, tx 4, client_state=1
E/        (  217): csd_client_disable_device: Disable received in invalid state:1
D/        (  217): csd_client_enable_device: APQ rx 7, tx 34, ec 43, tty 0x10012 state 1
D/        (  217): csd_client_enable_device: Remote rx -1, tx -1
E/        (  217): csd_client_enable_device: Enable received in invalid state 1
D/        (  217): csd_client_start_voice: State 1
D/        (  217): csd_client_async_cb: msg_id 0x33 result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x34 result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x55 result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x5c result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x4c result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x4c result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x57 result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x36 result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x3e result 0 error 0
D/        (  217): csd_client_async_cb: msg_id 0x36 result 0 error 0
D/        (  217): csd_client_volume: volume 0, state 2, rc 0
D/        (  217): csd_client_async_cb: msg_id 0x37 result 0 error 0
D/        (  217): csd_client_set_rx_mute: mute 0, state 2, rc 0
D/        (  217): csd_client_async_cb: msg_id 0x3e result 0 error 0
D/        (  217): csd_client_mic_mute: mute 0, state 2, rc 0
D/        (  217): csd_client_async_cb: msg_id 0x36 result 0 error 0
D/        (  217): csd_client_volume: volume 4, state 2, rc 0
D/        ( 6801): csd_client_init
E/        ( 6801): csd_client_service_init: Invalid rx device 0, setting to handset
E/        ( 6801): csd_client_service_init: Invalid tx device 0, setting to handset
D/        (  217): csd_client_stop_voice: State 2
D/        (  217): csd_client_async_cb: msg_id 0x58 result 1 error 3
E/        (  217): csd_client_stop_voice: Error -1 stopping voice manager
E/ALSADevice(  217): s_close: csd_client error -1

PID 217 是设备上的原始 csd_client,PID 6801 是我的可执行文件。

我的可执行文件进行客户端初始化并在建立调用后一起调用 libcs​​d-client.so 上的“csd_start_recording”。从日志中可以看出,“真正的”csd-client 显然正在与调制解调器进行双向通信,方法是在设备启动时注册一些回调并从那时起调节音频设置。例如,“csd_client_start_voice”在呼叫通过时由 HAL 调用。我怀疑我伪造的 csd-client 错过了所有这些中间状态,因此未能达到目的。

无论如何,现阶段的信息真的很有限,我感觉就像在黑暗中拍摄。希望有人可以在这里提供帮助。

【问题讨论】:

您在 QMI 日志中究竟看到了什么? 我已经确认 csd_client_service_init: Invalid rx device 0, setting to handset csd_client_service_init: Invalid tx device 0, setting to handset 没关系,因为 /system/bin/mediaserver 初始化的 csd-client 在启动时也会发出它们。 您确定设备使用的是您链接到的 AudioPolicyManagerBase 版本吗?由于它是一个高通平台,它似乎更有可能运行基于what's available at the CodeAurora Forum 的东西。 @Michael 是的,我想我很确定三星不是基于 CodeAurora 的AudioPolicyManagerBase。相反,我认为他们引用了 Google git 中的特定版本,该版本用于 Nexus 4 实现。我可以说我很确定,因为如果我在 AudioRecord 上使用 MediaRecorder.AudioSource.VOICE_DOWNLINKAudioPolicyManagerBase 会抱怨错误日志说“无法获取输入配置文件......”并且它会在请求中打印出通道掩码,这不是在 CodeAurora 上定义的,而是在 Google 的源代码中定义的。 【参考方案1】:

我有办法。基本上,您必须调用 medisaserver,因为除非您是该语音会话的所有者,否则 libcs​​d 中的 nothing 内容将起作用。 avs234.net/temp/csd_calls.c

【讨论】:

以上是关于是否可以动态链接到 libcs​​d-client.so 以在 Galaxy S4 I9505 上启用通话录音的主要内容,如果未能解决你的问题,请参考以下文章

gcc默认链接到libc.a或libc.so吗?

在 emscripten 中禁用链接 libc

每次加载libc地址都不相同

PWN菜鸡入门之栈溢出 —— ret2libc与动态链接库的关系

为啥Linux上的动态链接可执行文件在自己的内存空间中拥有libc的完整内存空间?

Go 的构建模式