Android AudioRecord强制另一个流到MIC音频源


81

更新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 / ++知识。如何确定是否可以从本机端调用这些方法?由于其他应用程序可以,因此必须有一种方法。


我每天至少要花5-6个小时来努力解决40余天。我不确定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的权限,这是正常权限,我的应用程序也具有此权限。这似乎是最重要的部分,并且看起来这三个公司都在使用JNI来执行他们触发VOICE_CALL音频源到MIC的流传输/合并以及使用Standart 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知识)试图使用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();
    }

}

显然,我缺少使录音成为可能的东西。

我什至提出要付费以获取此信息,但所有人都拒绝了。我说的还算公平。我将发布一次/如果找到它!

您对他们可能在做什么有任何想法吗?


您可以链接成功完成操作的应用程序吗?
roarster's


您发布了最后一个两次。
shmosel


1
您是否尝试对其进行反编译,以便进行窥视?(仅用于研究目的;))
布达·加夫里尔

Answers:


9

我和我的伴侣能够购买我们想要的东西。我们走在正确的道路上,您在本机端设置了keyValuePairs。

不幸的是,由于我们为我们撰写的公司的许可限制,我无法发布资源


3
一个人的错误是另一个人的特征。
Elwin Arens

7
是的,nLL是ACR,如果他无法分享解决方案,为什么他使用这个stackoverflow社区?我认为这完全违背了社区的主要动机。我保证,如果我能得到解决方案,我将立即发布解决方案,因为我相信开源。
japanjot singh

2
@japanjotsingh让我们一起找到解决方案
Peter

3
@nLL我可能听起来很粗鲁,但是兄弟,这对我们所有人来说都是非常沮丧的:-(
japanjot singh 17/09/29 '12

2
CallRecLib是一个提供用于在Android 6上录制电话对话的黑客的库github.com/ViktorDegtyarev/CallRecLib
Viktor Degtyarev

0

您的发现很有趣。我参与了一些涉及AudioRecordAPI的小型项目。希望以下内容会有所帮助:

假设您要设置一个AudioRecord实例,以便可以以16kHz的频率录制16位单声道。您可以通过使用一些辅助方法创建一个类来实现此目的,如下所示:

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


1
不,不幸的是,这与我的问题无关。我已经在使用AudioReocord类,并且已广泛使用它。
nLL

你解决了这个问题吗?我真的需要一个
可行的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.