Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To elaborate on an00b:s answer above and the edited version of the question we have to dig deeper into the source code. IAudioflinger is the interface to the AudioFlinger service and the call to</p> <pre><code>virtual status_t setMicMute(bool state) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(state); remote()-&gt;transact(SET_MIC_MUTE, data, &amp;reply); return reply.readInt32(); } </code></pre> <p>is actually the Binder transaction to mute the microphone. The receiving side of the Binder call looks like:</p> <pre><code>status_t BnAudioFlinger::onTransact(uint32_t code, const Parcel&amp; data, Parcel* reply, uint32_t flags) { switch(code) { ... case SET_MIC_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int state = data.readInt32(); reply-&gt;writeInt32( setMicMute(state) ); return NO_ERROR; } break; ... } } </code></pre> <p>and calls to the actual implementation of setMicMute in the <a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=services/audioflinger/AudioFlinger.cpp;h=c68e20d6304072d88f7a79180ffe845b5ad0eac1;hb=a8313e71fe8b483448d14e22610101c5f3672744" rel="nofollow noreferrer">AudioFlinger</a>. Next step is to look at this function:</p> <pre><code>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-&gt;setMicMute(state); mHardwareStatus = AUDIO_HW_IDLE; return ret; } </code></pre> <p>Here we can note two things. The first is that there is a permissions check to be able to mute the microphone. The permission being checked for in settingsAllowed is android.permission.MODIFY_AUDIO_SETTINGS so as mentioned in one of the comments above the first requirement for muting the microphone is that your application has declared that it needs this permission. The next thing to note is that we now call in to the hardware specific version of setMicMute using mAudioHardware->setMicMute(state). </p> <p>For more info on the way the hardware is plugged study the file AudioHardwareInterface.cpp. Basically it ends up in a libhardware with an extern C call to createAudioHardware which plugs in the correct AudioHardWare for the platform. There are also switches for using an A2DP based hardware, a generic one for the emulator and stubbing the audio. Assumed that you are working on an actual device the implementation is then very much hardware depending. To get a feel for it we can use the available audiohardware from Crespo (Nexus S) as an example. </p> <pre><code>status_t AudioHardware::setMicMute(bool state) { LOGV("setMicMute(%d) mMicMute %d", state, mMicMute); sp&lt;AudioStreamInALSA&gt; 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-&gt;standby(); } return NO_ERROR; } </code></pre> <p>Based on this example we may wrap up with a discussion of the implementation of audio routing in smartphones. As you can see in the Crespo implementation the mic mute call will only be respected if you are not in a call. The reason for this is that audio is routed through the analog baseband which handles power regulation, amplification and other things. When in a call the voice audio is often handled by analog baseband and modem CPU together and is not routed throught the application CPU. In that case you may need to go through the modem CPU through the RIL in order to mute the microphone. But since this behavior is hardware dependent there is no general solution.</p> <p>To give the short version to your 4 additional questions:</p> <ol> <li><p>The flag is passed on through several layers of code until it ends up in the hardware specific mute microphone.</p></li> <li><p>The mic is disconnected when the hardware specific code has run except when in a call at least on some devices.</p></li> <li><p>When setMicrophoneMute does not mute the mic, i.e. when in a call it may be possible to do that using one of the telephony API:s, I would suggest studying the phone app.</p></li> <li><p>Based on the current implementation mute seems to work when not in a call but there may be hardware specific issues on platforms we have not studied here.</p></li> </ol> <p><strong>EDIT:</strong></p> <p>Did some more digging and the way to send a mute command to the modem CPU is via the internal Phone interface that is part of the com.android.internal.telephony package that is not available to SDK developers. Based on the comment you saw that this function should only be used by applications that replace audio management or the original telephony application I would guess that AudioManager.setMicrophoneMute() was supposed to always mute the microphone regardless. But since other applications probably use this they added a check in the hardware implementation in order not to mess up the state of the phone application which keeps track of muted connections as well as the microphone. The function is probably not working as supposed to right now due to hardware implementation details and the fact that mute is a much more complex operation than one would initially think when considering call states as well.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COWow! I couldn't have expected a better answer than this. an00b's answer was a good starting point but you certainly delved into the deepest level, which is what I needed to understand why it doesn't work for me when `RecognitionListener` is listening. That is, if I try to call `mAudioManager.setMicrophoneMute(true)` inside `RecognitionListener.onReadyForSpeech()`, nothing happens: The microphone continues to accept speech as if Mute were never called. And **there is no call in progress!** Does this mean that Google's `RecognitionListener` sets AudioSystem::MODE_IN_CALL?
      singulars
    2. COI just found another version of [AudioHardware.cpp](http://vogue-android.googlecode.com/hg/AudioHardware.cpp) which implements it in an even much more complex manner... And all I wanted is simply to briefly disconnect the microphone while in `onReadyForSpeech()`... Is there a way to accomplish this at all? What does replacing audio management entail?
      singulars
    3. COI would need to dig a bit more into the Audio code again to answer your question about onReadyForSpeech() but so far I would say it seems that the API function AudioManager.setMicroPhoneMute() does not really reflect the complexity of audio routing in modern smartphones. That probably means that there is no generic way to implement what you want since each hardware platform seem to handle muting the microphone in different ways. I will edit this comment if I find a way.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload