1. ホーム
  2. java

[解決済み] Android AudioRecord MICオーディオソースに別のストリームを強制する

2023-06-26 08:21:20

質問

更新3: 私は別の開発者と提携し、我々は多額のお金のためにこれを行うことができます誰かを見つけたようだ。彼らは私たちにテストapkを送信しており、それは動作するように思われる。私たちは先に進み、ソースを購入する予定です。詐欺に遭わないことを祈ります。私は私が見つける一度更新されます

更新2です。 まだそれに取り組んでいます。もっと辛い日々の後、私は今、何も派手なことはしていないと思いますが、彼らは単にAudioFlinger ( リンク参照 ) をネイティブ側で呼び出して AudioFlinger::setParametersを呼び出します。

私は今、AudioFlinger::setParametersを次のように呼び出す簡単なJNIをどのように書けばよいかを探しています。 audio_io_handle_t ioHandle, const String8& keyValuePairsを呼び出す簡単なJNIを書きたいのですが、どうすればよいでしょうか?

私は何ができるかを知っています keyValuePairs は知っていますが audio_io_handle_t

更新しました。 私は今、他のアプリがCAFでQCOMオーディオを使用しているかもしれないと考えています。audio_extn_utils_send_audio_calibration を参照してください。 のリンクを参照してください。

で、voice_get_incall_rec_snd_deviceは のリンクで、同じ

私はC/++の知識がありません。ネイティブ側からこれらのメソッドを呼び出せるかどうかを調べるにはどうしたらよいでしょうか。 他のアプリができるのだから、方法があるはずです。


40日以上、1日5~6時間以上、この問題と格闘しています。SOで許可されているかどうかわかりませんが、私も正解のために寄付をすることをうれしく思います。

私はVOICE_CALLオーディオソースを使用する通話録音アプリを持っています。ASOP はそれを実装/義務化していませんが、ほとんどのメーカーは VOICE_CALL を実装しており、VOICE_CALL 音声ソースを使用するアプリは多くのデバイスで問題なく動作しました。Android 6まではそうでした。

VOICE_CALLの音源を開くには、システムアプリケーションにのみ許可されるandroid.permission.CAPTURE_AUDIO_OUTPUTが必要になりました。

これは本質的に通話録音を停止させるものです。この制限を回避する方法を見つけた 3 社を除いて、私のアプリと 200 以上の他の通話録音アプリでそうなっています。

私はそれらのアプリを Android 6 を搭載した多くの異なる機種で試してみて、録音を管理する方法にある種の特徴があることを発見しました。

彼らはすべて Android AudioRecord クラスとオープン MIC オーディオソースを使用しています。私もそうですが、私のアプリでは、MIC からの音声のみを取得し、相手からの音声は取得しません。私が発見したことは、録音を開始した直後または前に、何らかのシステム コールを発行していることを物語っています。

VOICE_CALL の録音に成功したアプリの 1 つで、録音に 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 で始まっています。

そして、2行目で何かをして、android.permission.MODIFY_AUDIO_SETTINGSを取得しています。これは通常の権限で、私のアプリもそれを取得しています。これは最も重要な部分のようで、3つともJNIを使用して、VOICE_CALLオーディオソースのMICへのストリーミング/マージと標準のAudioRecorder APIでの録音をトリガーしているように見えます。

次の行では、オーディオハードウェアが、MIC(1)オーディオソースを開いているにもかかわらず、VOICE_CALL (input_source=4)をミキシングし始めたことがわかります。

私は、彼らが

AudioManager.setParameters("key=value")

といったバリエーションを試しました。

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

運悪く

それから、私は Android、NDK、オーディオ ルーティング、ヘッドセットを介してオーディオを強制する を見つけ、それらが何らかの方法で現在の AudioRecord セッションに VOICE_CALL を混合/ルート/ストリーム/マージしているのではないかと考え、(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();
    }

}

明らかに、録音を可能にするために私が見逃している何かがあります。

私はこの情報を得るためにお金を払うとさえ申し出たが、すべて拒否された。十分公平だと私は言っています。私は一度/それを見つけた場合、それを公開するつもりです!

彼らが何をしているのか、何か心当たりはありますか?

どのように解決するのですか?

私と私のパートナーは、探していたものを購入することができました。ネイティブ側で keyValuePairs を設定したのは正解でした。

残念ながら、書いてもらった会社のライセンス制限のため、ソースを公開することができません。