上記の an00b:s の回答と質問の編集版について詳しく説明するには、ソース コードをさらに深く掘り下げる必要があります。IAudioflinger は、AudioFlinger サービスへのインターフェースであり、
virtual status_t setMicMute(bool state)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(state);
remote()->transact(SET_MIC_MUTE, data, &reply);
return reply.readInt32();
}
実際には、マイクをミュートする Binder トランザクションです。Binder 呼び出しの受信側は次のようになります。
status_t BnAudioFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch(code) {
...
case SET_MIC_MUTE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
int state = data.readInt32();
reply->writeInt32( setMicMute(state) );
return NO_ERROR;
} break;
...
}
}
AudioFlinger でsetMicMuteの実際の実装を呼び出します。次のステップは、この関数を確認することです。
status_t AudioFlinger::setMicMute(bool state) {
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
status_t ret = mAudioHardware->setMicMute(state);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
}
ここで、2 つのことがわかります。1 つ目は、マイクをミュートできる権限チェックがあることです。settingsAllowed でチェックされる許可は android.permission.MODIFY_AUDIO_SETTINGS であるため、上記のコメントの 1 つで述べたように、マイクをミュートするための最初の要件は、アプリケーションがこの許可が必要であることを宣言していることです。次に注意すべきことは、mAudioHardware->setMicMute(state) を使用して setMicMute のハードウェア固有バージョンを呼び出していることです。
ハードウェアを接続する方法の詳細については、ファイル AudioHardwareInterface.cpp を調べてください。基本的には、プラットフォームの正しい AudioHardWare をプラグインする createAudioHardware への extern C 呼び出しを含む libhardware になります。A2DP ベースのハードウェア、エミュレーター用の一般的なハードウェア、およびオーディオのスタブを使用するためのスイッチもあります。実際のデバイスで作業していると仮定すると、実装はハードウェアに大きく依存します。例として、Crespo (Nexus S) から入手可能なオーディオハードウェアを使用して、その感触をつかむことができます。
status_t AudioHardware::setMicMute(bool state) {
LOGV("setMicMute(%d) mMicMute %d", state, mMicMute);
sp<AudioStreamInALSA> spIn;
{
AutoMutex lock(mLock);
if (mMicMute != state) {
mMicMute = state;
// in call mute is handled by RIL
if (mMode != AudioSystem::MODE_IN_CALL) {
spIn = getActiveInput_l();
}
}
}
if (spIn != 0) {
spIn->standby();
}
return NO_ERROR;
}
この例に基づいて、スマートフォンでのオーディオ ルーティングの実装についての議論で締めくくることができます。Crespo の実装でわかるように、マイク ミュート コールは、通話中でない場合にのみ尊重されます。その理由は、電力調整、増幅などを処理するアナログ ベースバンドを介してオーディオがルーティングされるためです。通話中の音声は、多くの場合、アナログ ベースバンドとモデム CPU によって一緒に処理され、アプリケーション CPU を介してルーティングされません。その場合、マイクをミュートするために、RIL を介してモデム CPU を通過する必要がある場合があります。しかし、この動作はハードウェアに依存するため、一般的な解決策はありません。
4 つの追加の質問に短いバージョンを与えるには:
フラグは、ハードウェア固有のミュート マイクに到達するまで、複数のコード レイヤーを介して渡されます。
少なくとも一部のデバイスでの通話中を除き、ハードウェア固有のコードが実行されると、マイクが切断されます。
setMicrophoneMute がマイクをミュートしない場合、つまり通話中にテレフォニー API の 1 つを使用してミュートできる可能性がある場合は、電話アプリを検討することをお勧めします。
現在の実装に基づくと、通話中でない場合はミュートが機能しているように見えますが、ここでは調査していないプラットフォームにハードウェア固有の問題がある可能性があります。
編集:
さらに掘り下げて、モデム CPU にミュート コマンドを送信する方法は、SDK 開発者が利用できない com.android.internal.telephony パッケージの一部である内部電話インターフェイスを介することです。この関数は、オーディオ管理を置き換えるアプリケーションまたは元の電話アプリケーションでのみ使用する必要があるというコメントに基づいて、 AudioManager.setMicrophoneMute() は常にマイクをミュートするはずだったと思います。しかし、他のアプリケーションはおそらくこれを使用しているため、ミュートされた接続とマイクを追跡する電話アプリケーションの状態を台無しにしないように、ハードウェア実装にチェックを追加しました。