更新 3:我已与另一位开发人员合作,我们似乎找到了能以大笔资金做到这一点的人。他们向我们发送了一个测试 apk,它似乎有效。我们将继续购买源代码。我希望我们不会被骗。知道后我会更新
更新 2:仍在努力。经过更痛苦的日子后,我现在认为没有什么特别的事情发生,但他们只是在本机端使用 AudioFlinger (参见链接)来调用AudioFlinger::setParameters
我现在正在寻找如何编写一个简单的 JNI 来使用 audio_io_handle_t ioHandle、const String8& keyValuePairs 调用 AudioFlinger::setParameters
我知道keyValuePairs可以是什么,但不知道audio_io_handle_t
更新:我现在相信其他应用程序可能正在使用带有 CAF 的 QCOM 音频。请参阅链接中的 audio_extn_utils_send_audio_calibration 以获得相同的信息
和 voice_get_incall_rec_snd_device相同的链接
我没有 C/++ 知识。我怎样才能知道我是否可以从本机端调用这些方法?既然其他应用可以,那一定有办法。
40 多天以来,我每天至少要为此苦苦挣扎 5-6 个小时。我不确定 SO 是否允许,但我也很乐意为正确答案捐款。
我有一个使用 VOICE_CALL 音频源的通话录音应用程序。尽管 ASOP 没有实现/强制它,但大多数制造商已经实现了 VOICE_CALL,并且使用 VOICE_CALL 音频源的应用程序在许多设备上都可以正常工作。直到Android 6。
Google 在 Android 6 中改变了这种行为。现在打开 VOICE_CALL 音频源需要 android.permission.CAPTURE_AUDIO_OUTPUT,它只授予系统应用程序。
这基本上停止了通话录音,或者应该有。好吧,它适用于我和 200 多个其他通话记录应用程序,除了 3 个找到解决此限制的方法。
我一直在使用 Android 6 的许多不同手机上尝试这些应用程序,并在它们设法记录的方式中发现了某些特征。
他们都使用 Android AudioRecord 类并打开 MIC 音频源。我也做; 但在我的应用程序上,我只能从 MIC 获取音频,而不是对方。我发现告诉我他们在开始录制之后或之前发出某种系统调用。
查看以下日志,其中一个成功记录了 VOICE_CALL 的应用程序,即使它使用 MIC 进行记录。看起来应用程序是一些如何管理将 VOICE_CALL 音频源混合/路由/流/合并到 MIC 的方法。
- D/audio_hw_primary: in_set_parameters: enter: kvpairs=input_source=1;routing=-2147483644
- D/PermissionCache: checking android.permission.MODIFY_AUDIO_SETTINGS for uid=10286 => granted (432 us)
- D/audio_hw_primary: in_set_parameters: enter: kvpairs=input_source=4;routing=-2147483584;format=1
- D/audio_hw_primary: select_devices: out_snd_device(0: ) in_snd_device(283: voice-dmic-ef)
- D/hardware_info: hw_info_append_hw_type : device_name = voice-dmic-ef
- D/voice: voice_get_incall_rec_snd_device: in_snd_device(283: voice-dmic-ef) incall_record_device(283: voice-dmic-ef)
正如您在第一行中看到的,它以 MIC 音频源 input_source=1;routing=-2147483644 开头。
然后,在第二行它做了一些事情并获得了 android.permission.MODIFY_AUDIO_SETTINGS 这是正常权限,我的应用程序也有它。这似乎是最重要的部分,看起来所有 3 人都在使用 JNI 来执行他们所做的任何事情来触发将 VOICE_CALL 音频源流式传输/合并到 MIC 并使用标准 AudioRecorder API 进行录制
在下一行,您会看到音频硬件开始混合 VOICE_CALL (input_source=4),即使它们已打开 MIC(1) 音频源。
我假设他们使用
AudioManager.setParameters("key=value")
并尝试了许多变化,例如
AudioManager.setParameters("input_source=4;routing=-2147483584;format=1")
没有任何运气。
然后,我发现了Android、NDK、音频路由,通过耳机强制音频,并认为它们可能是一些如何将 VOICE_CALL 混合/路由/流/合并到当前 AudioRecord 会话并且(因为没有 C 知识)尝试使用重新定义用下面的代码(再次)实现同样的事情没有运气。
private static void setForceUseOn() {
/*
setForceUse(int usage, int config);
----usage for setForceUse, must match AudioSystem::force_use
public static final int FOR_COMMUNICATION = 0;
public static final int FOR_MEDIA = 1;
public static final int FOR_RECORD = 2;
public static final int FOR_DOCK = 3;
public static final int FOR_SYSTEM = 4;
public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
----device categories config for setForceUse, must match AudioSystem::forced_config
public static final int FORCE_NONE = 0;
public static final int FORCE_SPEAKER = 1;
public static final int FORCE_HEADPHONES = 2;
public static final int FORCE_BT_SCO = 3;
public static final int FORCE_BT_A2DP = 4;
public static final int FORCE_WIRED_ACCESSORY = 5;
public static final int FORCE_BT_CAR_DOCK = 6;
public static final int FORCE_BT_DESK_DOCK = 7;
public static final int FORCE_ANALOG_DOCK = 8;
public static final int FORCE_DIGITAL_DOCK = 9;
public static final int FORCE_NO_BT_A2DP = 10;
public static final int FORCE_SYSTEM_ENFORCED = 11;
public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
public static final int FORCE_DEFAULT = FORCE_NONE;
*/
try {
Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
setForceUse.invoke(null, 0, 0); // setForceUse(FOR_RECORD, FORCE_NONE)
} catch (Exception e) {
e.printStackTrace();
}
}
显然,我缺少一些使录音成为可能的东西。
我什至提出要付钱来获取这些信息,都被拒绝了。我已经说过了。我将发布一次/如果我找到它!
你知道他们可能在做什么吗?