'AWS Chime (webrtc audio) + Oculus Quest 2 - setStreamVolume does not change real volume even if getStreamVolume shows a different value

I use Amazon's AWS Chime to establish voip audio communication . My actual setup is a bit complicated, I built chime android sdk into a module, with some changes to remove the video part, and included it in my Unity based Oculus Quest 2 App. However, I also tested Chime's demo app, sending directly the APK to the Quest 2 via Android Studio; it runs and connects correctly to a meeting, streaming audio and even the chat.

Unfortunately, changing the audio volume with hardware buttons does not have any effect.

I added the following snippet to the demo app, for testing purposes

 val audioManager = getContext()?.getSystemService(AUDIO_SERVICE) as AudioManager
    Log.d("1234", "audiomanager mode " + audioManager.mode);

    val observer: ContentObserver = object : ContentObserver(Handler(Looper.myLooper())) {
        override fun onChange(selfChange: Boolean, uri: Uri?) {
            super.onChange(selfChange, uri)
            val audioManager = getContext()?.getSystemService(AUDIO_SERVICE) as AudioManager
            Log.d("1234", "new ONCHANGE system settings " + uri.toString() + " current mode " + audioManager!!.mode)
            Log.d("1234", "ONCHANGE stream MUSIC current " + audioManager!!.getStreamVolume(AudioManager.STREAM_MUSIC))
            Log.d("1234", "ONCHANGE stream VOICe CALL current " + audioManager!!.getStreamVolume(AudioManager.STREAM_VOICE_CALL))
            Log.d("1234", "ONCHANGE stream STREAM_ACCESSIBILITY current " + audioManager!!.getStreamVolume(AudioManager.STREAM_ACCESSIBILITY))
            Log.d("1234", "ONCHANGE stream STREAM_ALARM current " + audioManager!!.getStreamVolume(AudioManager.STREAM_ALARM))
            Log.d("1234", "ONCHANGE stream STREAM_DTMF current " + audioManager!!.getStreamVolume(AudioManager.STREAM_DTMF))
            Log.d("1234", "ONCHANGE stream STREAM_NOTIFICATION current " + audioManager!!.getStreamVolume(AudioManager.STREAM_NOTIFICATION))
            Log.d("1234", "ONCHANGE stream STREAM_RING current " + audioManager!!.getStreamVolume(AudioManager.STREAM_RING))
            Log.d("1234", "ONCHANGE stream STREAM_SYSTEM current " + audioManager!!.getStreamVolume(AudioManager.STREAM_SYSTEM))
        }
    }
    getContext()?.getContentResolver()?.registerContentObserver(Settings.System.CONTENT_URI, true, observer)

First of all, on the Quest, every change happens on uri content://settings/system/volume_music_speaker and upon connection the Audiomanage.getMode() changes from 0 to 3 MODE_IN_COMMUNICATION.

After recent Oculus software updates, every change on one audio stream is automagically applied to all the others. That is why if I press the hardware volume buttons two times, this is what my logs show

D/1234: new ONCHANGE system settings content://settings/system/volume_music_speaker current mode 3
D/1234: ONCHANGE stream MUSIC current 6
D/1234: ONCHANGE stream VOICe CALL current 3
D/1234: ONCHANGE stream STREAM_ACCESSIBILITY current 7
D/1234: ONCHANGE stream STREAM_ALARM current 3
D/1234: ONCHANGE stream STREAM_DTMF current 6
D/1234: ONCHANGE stream STREAM_NOTIFICATION current 3
D/1234: ONCHANGE stream STREAM_RING current 3
D/1234: ONCHANGE stream STREAM_SYSTEM current 3

D/1234: new ONCHANGE system settings content://settings/system/volume_music_speaker current mode 3
D/1234: ONCHANGE stream MUSIC current 5
D/1234: ONCHANGE stream VOICe CALL current 2
D/1234: ONCHANGE stream STREAM_ACCESSIBILITY current 6
D/1234: ONCHANGE stream STREAM_ALARM current 3
D/1234: ONCHANGE stream STREAM_DTMF current 5
D/1234: ONCHANGE stream STREAM_NOTIFICATION current 2
D/1234: ONCHANGE stream STREAM_RING current 2
D/1234: ONCHANGE stream STREAM_SYSTEM current 2

Showing that all the streams change value (each of them with respect to their own max/min values. e.g. CALL from 1 to 5 etc)

The problem is that even when I arrive in this situation

D/1234: new ONCHANGE system settings content://settings/system/volume_music_speaker current mode 3
D/1234: ONCHANGE stream MUSIC current 0
D/1234: ONCHANGE stream VOICe CALL current 1
D/1234: ONCHANGE stream STREAM_ACCESSIBILITY current 1
D/1234: ONCHANGE stream STREAM_ALARM current 1
D/1234: ONCHANGE stream STREAM_DTMF current 0
D/1234: ONCHANGE stream STREAM_NOTIFICATION current 0
D/1234: ONCHANGE stream STREAM_RING current 0
D/1234: ONCHANGE stream STREAM_SYSTEM current 0

The actuall volume of the person talking to me does not go down.

Chime's main sdk relies on a precompiled secondary sdk, released by the developers, the code of which is not public. I decompiled it with JD GUI but the methods with actual stuff in it are protected. I was only able to see that in their webrtc library, an AudioTrack is instantiated and used to stream the voice bytes, and it is set to AudioSessioId 0 . AudioManager sets mode to 3, and nothing else (visible). If I had a reference to the AudioTrack, I could try changing volume directly but it is not exposed.

I tried:

  • decompiling the media sdk to see what's going on, but it is protected.
  • looking for ongoing AudioSessions by registering as a NotificationListenerService and calling MediaSessionManager#getActiveSessions, but no session coming from chime is present (spotify in background does appear, so my code works)
  • doingAudioManager.setMode(0), but even if the mode changes, the volume still doesn't go down.
  • attaching an audiofx.Equalizer to session 0 (deprecated) just to see if I could change the gain of all the bands and lower the global output mix's volume. But it has no effect on session 0 . (I double checked my code applying the eq to a test AudioTrack and a test MediaPlayer, it worked in both cases)
  • considered using the NDK to access the AudioFlinger, but it reaally looks complicated and overkill.
  • writing an issue on Chime's github repo, where it's difficult to get an answer because I'm on quest and the app is designed for Android, where the audio volume does change
  • writing a test android app where I created an AudioTrack in streaming mode, set its attributes to USAGE_VOICE_COMMUNICATION and CONTENT_TYPE_SPEECH, changed AudioManager's mode to 3 and run it on Oculus Quest via Android Studio. The audio changed correctly both with pression of hardware volume button and programmatically. So it must be something the chime hidden media sdk does that is not compatible with Quest's Android.

Eventually, what I don't understand is how it is possible that a third-party webrtc library is able to play an AudioTrack in MODE_IN_COMMUNICATION and even if I programmatically lower the volume of every stream such as AudioManager.STREAM_MUSIC , AudioManager.STREAM_VOICE_CALL etc, the actual volume does not change while the getStreamVolume() says otherwise. And also, how is it possible that a third party library is allowed to play audio, and there is no way for a dev to access all playing stuff and control them.

I hope somebody more experienced than me in both Android audio stuff and Oculus Quest inner shenanigans can shed some light on what is happening.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source