¿Cómo funciona setMicrophoneMute ()?

He estado intentando utilizar AudioManager.setMicrophoneMute() de Android AudioManager.setMicrophoneMute() sin mucho éxito. Es decir, simplemente se niega a silenciar el micrófono, no importa lo que hago.

Busqué en la web algunas pistas y encontré varias referencias que reportan experiencia similar:

  • AudioManger.setMicrophoneMute funcionalidad no funciona ??
  • SetMicrophoneMute (boolean) no funciona en algunos dispositivos
  • No se puede silenciar el micrófono en Android

Lo que plantea la pregunta: ¿ AudioManager.setMicrophoneMute() funciona en absoluto? ¿Es sólo un método stub, a la espera de ser implementado en alguna futura versión de Android? Si no, ¿cómo funciona? ¿Qué necesito para que funcione? ¿Cuáles son las condiciones que lo hacen funcionar como su nombre lo indica?

EDIT: Me di cuenta de que la documentación de este método dice:

Este método sólo debe ser utilizado por aplicaciones que reemplacen la gestión de toda la plataforma de configuración de audio o la aplicación de telefonía principal.

¿Qué significa esto? ¿Por qué querría reemplazar la gestión de toda la plataforma? ¿Realmente necesito hacer eso? Si es así, ¿cómo hago eso?

EDIT: La respuesta a continuación es genial, pero todavía no entiendo:

  1. ¿Cómo se usa esa bandera (SET_MIC_MUTE en la base de datos)?
  2. ¿Cuándo esta bandera desconecta realmente la señal del micrófono del circuito del preamplificador dentro del teléfono?
  3. Si no lo hace, ¿quién hace eso?
  4. Si nada hace eso, ¿cómo se espera que este "silencio" funcione?

Por favor explique. Gracias.

Para elaborar sobre la respuesta anterior y la versión editada de la pregunta tenemos que profundizar en el código fuente. IAudioflinger es la interfaz para el servicio AudioFlinger y la llamada a

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

Es en realidad la transacción Binder para silenciar el micrófono. El lado de recepción de la llamada Binder tiene el siguiente aspecto:

  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; ... }} 

Y las llamadas a la implementación real de setMicMute en el AudioFlinger . El siguiente paso es examinar esta función:

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

Aquí podemos notar dos cosas. La primera es que hay una verificación de permisos para poder silenciar el micrófono. El permiso que se está comprobando en settingsAllowed es android.permission.MODIFY_AUDIO_SETTINGS, como se menciona en uno de los comentarios anteriores, el primer requisito para silenciar el micrófono es que su aplicación ha declarado que necesita este permiso. La siguiente cosa a tener en cuenta es que ahora llamamos a la versión específica del hardware de setMicMute usando mAudioHardware-> setMicMute (state).

Para más información sobre la forma en que el hardware está conectado estudiar el archivo AudioHardwareInterface.cpp. Básicamente termina en un libhardware con una llamada extern C a createAudioHardware que se conecta en el AudioHardWare correcto para la plataforma. También hay conmutadores para usar un hardware basado en A2DP, uno genérico para el emulador y el apagado del audio. Asumido que usted está trabajando en un dispositivo real la puesta en práctica es entonces mucho hardware dependiendo. Para conseguir una sensación para él podemos utilizar el audiohardware disponible de Crespo (Nexus S) como ejemplo.

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

Basándonos en este ejemplo, podemos concluir con una discusión sobre la implementación del enrutamiento de audio en teléfonos inteligentes. Como se puede ver en la implementación de Crespo, la llamada de mudo de micrófono sólo se respetará si no está en una llamada. La razón de esto es que el audio se enruta a través de la banda base analógica que maneja regulación de potencia, amplificación y otras cosas. Cuando en una llamada el audio de voz es manejado a menudo por la base de banda analógica y la CPU del módem juntos y no es dirigido a través de la CPU de la aplicación. En ese caso, es posible que necesite pasar por la CPU del módem a través del RIL para silenciar el micrófono. Pero como este comportamiento depende del hardware, no existe una solución general.

Para dar la versión corta a sus 4 preguntas adicionales:

  1. La bandera se transmite a través de varias capas de código hasta que termina en el micrófono de silencio específico del hardware.

  2. El micrófono se desconecta cuando el código específico del hardware se ha ejecutado, excepto cuando en una llamada al menos en algunos dispositivos.

  3. Cuando setMicrophoneMute no silencia el micrófono, es decir cuando en una llamada puede ser posible hacer eso usando una de las API de telefonía: s, sugeriría estudiar la aplicación del teléfono.

  4. Basado en la implementación actual mute parece funcionar cuando no en una llamada, pero puede haber problemas específicos de hardware en las plataformas que no hemos estudiado aquí.

EDITAR:

Hizo un poco más de excavación y la forma de enviar un comando de silencio a la CPU del módem es a través de la interfaz interna del teléfono que forma parte del paquete com.android.internal.telephony que no está disponible para los desarrolladores de SDK. Basado en el comentario que usted vio que esta función sólo debe ser utilizado por las aplicaciones que reemplazan la gestión de audio o la aplicación de telefonía original, supongo que AudioManager.setMicrophoneMute () se supone que siempre silenciar el micrófono independientemente. Pero como otras aplicaciones probablemente utilizan esto, agregaron una comprobación en la implementación del hardware para no estropear el estado de la aplicación del teléfono, que mantiene un registro de las conexiones silenciadas, así como del micrófono. La función probablemente no funciona como se supone ahora debido a los detalles de la implementación de hardware y el hecho de que el mudo es una operación mucho más compleja de lo que uno pensaría inicialmente al considerar los estados de llamada también.

Intente buscar el código fuente de AudioManager :

 public void setMicrophoneMute(boolean on){ IAudioService service = getService(); try { service.setMicrophoneMute(on); } catch (RemoteException e) { Log.e(TAG, "Dead object in setMicrophoneMute", e); } } 

La tarea de silenciar el micrófono se delega en un servicio denominado IAudioService :

 public void setMicrophoneMute(boolean on) { if (!checkAudioSettingsPermission("setMicrophoneMute()")) { return; } synchronized (mSettingsLock) { if (on != mMicMute) { AudioSystem.muteMicrophone(on); mMicMute = on; } } } 

Lo cual, a su vez, lo delega a AudioSystem que parece estar implementado en código nativo :

 status_t AudioSystem::muteMicrophone(bool state) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; return af->setMicMute(state); } 

Lo cual, a su vez, lo delega a IAudioFlinger como se puede encontrar en IAudioFlinger.cpp :

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

Chicos. Encontré los mismos problemas en Samsung Galaxy y resolví usar el modo MODE_IN_COMMUNICATION. Vi en el código fuente AudioManager.java, dice: 1.MODE_IN_CALL -'En el modo de llamada de audio. Se establece una llamada telefónica. 2.MODE_IN_COMMUNICATION -En el modo de audio de comunicación. Se establece un chat de audio / video o VoIP. ' Ya que uso el tercer librito de VOIP, entonces utilizo el MODE_IN_COMMUNICATION y solucioné el problema. Me gusta esto:

  AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // get original mode int originalMode = audioManager.getMode(); audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); // change mute boolean state = !audioManager.isMicrophoneMute(); audioManager.setMicrophoneMute(state); // set mode back audioManager.setMode(originalMode); 

Por alguna razón tengo errores al publicar esto como un comentario. He aquí alguna información que he aprendido sobre los dispositivos que setMicrophoneMute () hace y no funciona, y qué (pocas) maneras hay de trabajar a su alrededor, ¡ciertamente no es una solución perfecta! SetMicrophoneMute (boolean) no funciona en algunos dispositivos

  • Control del volumen de audio forzado a altavoz
  • Android: ¿Cómo generar una frecuencia?
  • Cambiar el volumen del timbre durante el timbre
  • ¿Cuál es el flujo de audio predeterminado de TTS?
  • ¿Cómo obtiene / establece el volumen de los medios (no el volumen del tono de timbre) en Android?
  • Android: forzar el micrófono externo (entrada jack 3,5 mm) para permanecer en
  • No se puede recuperar el puntero AudioTrack para write ()
  • AudioManager enviar mensaje a un manejador en un hilo muerto?
  • MediaPlayer cortar la reproducción demasiado pronto en Lollipop cuando la pantalla está apagada
  • Cómo configurar el volumen de sonido de notificación mediante programación?
  • Cómo pausar los reproductores de música en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.