Android AudioRecord强制另一个stream到MICaudio源

更新3:我与另一位开发人员合作,我们似乎find了一个能够为此花费大笔金钱的人。 他们给我们一个testingapk,它似乎工作。 我们将继续购买源代码。 我希望我们不会被骗。 一旦我发现,我会更新

更新2:仍然在努力。 经过更多痛苦的日子,我现在认为没有什么奇特的事情,但他们只是在本机端使用AudioFlinger( 请参阅链接 )来调用AudioFlinger :: setParameters

我现在正在寻找如何编写一个简单的JNI来调用AudioFlinger :: setParameters with audio_io_handle_t ioHandle,const String8&keyValuePair

我知道什么keyValuePairs可以但不是关于audio_io_handle_t的线索

更新:我现在相信其他应用程序可能正在使用与CAF的QCOMaudio。 请参阅链接 audio_extn_utils_send_audio_calibration 相同

和voice_get_incall_rec_snd_device在链接相同

我没有C / ++的知识。 我怎样才能知道是否可以从本地调用这些方法? 由于其他应用程序可以,一定有办法。


我一直在这个40多天的时间里挣扎,每天至less有5-6个小时。 我不确定这是否被允许,但我也乐意为正确的答案捐款。

我有一个使用VOICE_CALLaudio源的通话录音应用程序。 尽pipeASOP没有实施/强制执行,但大多数制造商已经实施了VOICE_CALL,使用VOICE_CALLaudio源的应用程序在许多设备上运行良好。 这是直到Android 6。

Google使用Android 6更改了此行为。现在打开VOICE_CALLaudio源需要android.permission.CAPTURE_AUDIO_OUTPUT,它只被授予系统应用程序。

这基本上停止了通话logging,或者它应该有。 那么,除了3个已经find解决这个限制的方法之外,它对我和其他200多个通话录音应用程序都有效。

我一直在用Android 6在许多不同的手机上试用这些应用程序,并发现了它们logging的某些特征。

他们都使用Android AudioRecord类并打开MICaudio源。 我也做; 但在我的应用程序中,我只从MIC获取audio,而不是另一方。 我发现,在开始录制之前或之后,他们正在发出某种系统调用。

查看下面的日志表单,即使使用MIClogging,也能成功loggingVOICE_CALL的应用程序之一。 它看起来像应用程序是如何pipe理混合/路由/stream/合并VOICE_CALLaudio源到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) 

正如您在第一行中看到的,它以MICaudio源input_source = 1; routing = -2147483644开始。

然后,在第二行它做了一些事情,并获得授予android.permission.MODIFY_AUDIO_SETTINGS这是正常的权限,我的应用程序也有。 这似乎是最重要的部分,它看起来像所有3使用JNI做他们做什么,以触发VOICE_CALLaudio源stream媒体/合并到MIC和logging与标准的AudioRecorder API

在下一行中,即使已打开MIC(1)audio源,也会看到audio硬件开始混合VOICE_CALL(input_source = 4)。

我假定他们用过

 AudioManager.setParameters("key=value") 

并尝试了很多变化,如

 AudioManager.setParameters("input_source=4;routing=-2147483584;format=1") 

没有任何运气。

然后,我发现Android,NDK,audio路由,通过耳机强制audio ,认为他们可能是一些如何混合/路由/stream/合并VOICE_CALL到当前AudioRecord会议和(因为没有C知识)试图使用reflation用下面的代码(再次)实现同样的事情没有运气。

 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(); } } 

显然有一些我错过了,使录音成为可能。

我甚至愿意付钱得到这些信息,都被拒绝了。 我已经说了很好。 我会发布一次/如果我find它!

你有什么想法,他们可能在做什么?

提前致谢。

我和我的伙伴能够购买我们正在寻找的东西。 我们在正确的道路上,你在本地设置keyValuePairs。

不幸的是,由于我们为其编写的公司的许可限制,我无法公布源代码

你的发现很有趣。 我曾经参与过一些涉及AudioRecord API的小型项目。 希望以下内容有所帮助:

假设您要设置一个AudioRecord实例,以便您可以以16kHz的16位单声道录制。 你可以通过创build一个带有一些辅助方法的类来达到这个目的,如下所示:

 public class AudioRecordTool { private final int minBufferSize; private boolean doRecord = false; private final AudioRecord audioRecord; public AudioRecordTool() { minBufferSize = AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); audioRecord = new AudioRecord( MediaRecorder.AudioSource.VOICE_COMMUNICATION, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 2); } public void writeAudioToStream(OutputStream audioStream) { doRecord = true; //Will dictate if we are recording. audioRecord.startRecording(); byte[] buffer = new byte[minBufferSize * 2]; while (doRecord) { int bytesWritten = audioRecord.read(buffer, 0, buffer.length); try { audioStream.write(buffer, 0, bytesWritten); } catch (IOException e) { //You can log if you like, or simply ignore it stopRecording(); } } //cleanup audioRecord.stop(); audioRecord.release(); } public void stopRecording() { doRecord = false; } } 

我猜你将需要保持相同的权限,因为棉花糖的用户是唯一的授予我们访问权限,如果不是几乎所有的酷。

尝试实施课程,让我们知道它是如何去的,我还留下一些额外的参考,以防您需要更多的研究。

祝你好运。

AudioRecord API

AudioCaputre API

MediaRecorder API

Interesting Posts