twilio / audioswitch

An Android audio management library for real-time communication apps.
Apache License 2.0
163 stars 50 forks source link

NullPointerException #89

Closed brian-chung-dragon closed 3 years ago

brian-chung-dragon commented 3 years ago

Describe the bug Received a couple of NullPointerException thrown from the AudioSwitch library

java.lang.NullPointerException: mutableAudioDevices[0] must not be null
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices(AudioSwitch.kt:285)
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices$default(AudioSwitch.kt:253)
    at com.twilio.audioswitch.AudioSwitch$wiredDeviceConnectionListener$1.onDeviceDisconnected(AudioSwitch.kt:68)
    at com.twilio.audioswitch.wired.WiredHeadsetReceiver.onReceive(WiredHeadsetReceiver.kt:31)
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52225(LoadedApk.java:1319)
    at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.$m$0
    at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.run
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.HEADSET_PLUG flg=0x40000010 (has extras) } in com.twilio.audioswitch.wired.WiredHeadsetReceiver@7998623
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52225(LoadedApk.java:1329)
    at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.$m$0
    at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.run
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Expected behavior The library itself will handle the NullPointerException properly

Actual behavior App crash due to NullPointerException

AudioSwitch Version 1.01

Android Device (please complete the following information): Device: Samsung Galaxy S8 (SG-G9500) OS: Android 8.0.0 Rooted: No API Version: 26

Alton09 commented 3 years ago

Hi @brian-chung-dragon . Can you please share the steps your app performs before running into this exception? Also, it would be very helpful if you could share the application logs with AudioSwitch logging enabled and filtering in logcat with AS/. Thank you!

brian-chung-dragon commented 3 years ago

Hi @Alton09 , unfortunately I couldn't reproduce this error in my real devices. The log I posted above is captured from Sentry and the exception happens in few of our customers.

brian-chung-dragon commented 3 years ago

Are we able to trace the root cause based on the stack trace? Thanks again

Alton09 commented 3 years ago

From looking at the logs it looks like there is a failure after connecting a wired headset. Does this happen only on the Samsung Galaxy S8? Or does it also occur on other devices? Also, your app may be using the library incorrectly and is resulting in this state. Do you mind sharing your app's code snippets that interact with AudioSwitch? Thanks!

Also, try upgrading AudioSwitch to the latest version 1.1.2.

brian-chung-dragon commented 3 years ago

Hi Alton09,

After checking the logs, there is another exception related to AudioSwitch and it is affecting non Samsung devices, for example, ASUS ROG Phone, ASUS_I001DE & MI Max 3

java.util.ConcurrentModificationException: null
    at java.util.ArrayList$Itr.next(ArrayList.java:860)
    at com.twilio.audioswitch.AudioSwitch.userSelectedDevicePresent(AudioSwitch.kt:316)
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices(AudioSwitch.kt:277)
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices$default(AudioSwitch.kt:253)
    at com.twilio.audioswitch.AudioSwitch$wiredDeviceConnectionListener$1.onDeviceDisconnected(AudioSwitch.kt:68)
    at com.twilio.audioswitch.wired.WiredHeadsetReceiver.onReceive(WiredHeadsetReceiver.kt:31)
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1397)
    at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6806)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.HEADSET_PLUG flg=0x40000010 (has extras) } in com.twilio.audioswitch.wired.WiredHeadsetReceiver@4f0afb2
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1407)
    at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6806)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

Attached please find the code snippets for our voice call. sample-code.zip

Hopefully, this issue will be fixed in 1.1.2 🤞

Alton09 commented 3 years ago

Thanks for sharing the additional stack trace and code snippetes @brian-chung-dragon ! Your app is doing a good job managing audio switch. The only snippet I find odd is this one:

        audioSwitch.start(new Function2<List<? extends AudioDevice>, AudioDevice, Unit>() {
            @Override
            public Unit invoke(List<? extends AudioDevice> audioDevices, AudioDevice audioDevice) {
                if (audioDevices != null && !audioDevices.isEmpty()) {
                    AudioDevice defaultAudioDevice = audioDevices.get(0);
                    if (!audioDevice.getName().equals(SPEAKER_PHONE) && !audioDevice.equals(defaultAudioDevice)) {
                        audioSwitch.selectDevice(defaultAudioDevice);
                    }
                }
                return Unit.INSTANCE;
            }
        });

What is this callback doing for your app? Also, this will get executed every time the list of available audio devices changes. This might be what could be leading to the crash.

Please do reach out again if you continue to experience the crash on 1.1.2. I'll keep investigating this crash in the meantime. Thanks!

brian-chung-dragon commented 3 years ago

I am using this callback to implement a feature that can make app switch the audio channel to bluetooth or wireless headset automatically

Example:

  1. Customer make voice call and using the speaker phone
  2. While waiting the agents answer the call, customer connected to his AirPods
  3. App will switch the audio channel to AirPods automatically
Alton09 commented 3 years ago

Hi @brian-chung-dragon . AudioSwitch now supports setting a custom preferredDeviceList to the AudioSwitch constructor. See this KDoc to learn how to use it. You can set BluetoothHeadset at the front of the list so it automatically gets selected in preference to other audio devices. I recommend switching to this approach as it might resolve the issue you are experiencing. Thanks!

Alton09 commented 3 years ago

Hi @brian-chung-dragon ! Did using the API above resolve your issue?

Alton09 commented 3 years ago

Closing this one for now due to inactivity. Please feel free to open any new issues as needed. Thanks!