NPE within ReadWriteListener$ReadWriteEvent.isNull



  • Hi,

    We just encountered the following exception:

        java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.idevicesinc.sweetblue.ReadWriteListener$Type.isNull()' on a null object reference
            at com.idevicesinc.sweetblue.ReadWriteListener$ReadWriteEvent.isNull(Unknown Source:4)
    

    This is surprising, since it seems we got a non-null ReadWriteEvent throws an NPE when we call isNull(), since it internally does type().isNull() but type() seems to return null.

    This seems like a bug in SweetBlue. Could this be the case?



  • Yes it's a bug, SweetBlue shouldn't throw any NPEs with normal usage. Could you provide more details on this case if possible? Was it a read, or write. Was it on a characteristic, descriptor, or other (such as RSSI, or connection priority, etc)? Type should never be null, so any help you can provide on narrowing the search would be appreciated.

    I assume this is on version 3, please let me know if that is not the case.



  • Hi, thanks for the response.

    We're using SweetBlue 3.0.2. This exception has occurred in the wild, without any clear indication as to why. However we've also managed to inconsistently reproduce it by toggling bluetooth off/on while a connection is open, then performing a write once the device state is CONNECTED.

    The 'corrupt' ReadWriteEvent is returned by BleDevice.write(BleWrite), and also posted through the bleManager.setListener_Read_Write callback.

    We've also noticed the following SweetBlue exceptions in the log:

    E/BleManager: ASSERTION FAILED Native server is already closed and nulled out.
        java.lang.Exception
            at com.idevicesinc.sweetblue.internal.P_BleManagerImpl.ASSERT(Unknown Source:22)
            at com.idevicesinc.sweetblue.internal.P_BleServerNativeManager.closeServer(Unknown Source:27)
            at com.idevicesinc.sweetblue.internal.P_BleServerImpl.disconnect_internal(Unknown Source:26)
            at com.idevicesinc.sweetblue.internal.P_BleManager_ListenerProcessor.handleBleTurningOff(Unknown Source:64)
            at com.idevicesinc.sweetblue.internal.P_BleManager_ListenerProcessor.onNativeBleStateChange(Unknown Source:433)
            at com.idevicesinc.sweetblue.internal.P_BleManager_ListenerProcessor.onNativeBleStateChangeFromBroadcastReceiver(Unknown Source:77)
            at com.idevicesinc.sweetblue.internal.P_BleManager_ListenerProcessor$BluetoothReceiver.onReceive(Unknown Source:14)
            at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1424)
            at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
            at android.os.Handler.handleCallback(Handler.java:873)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:193)
            at android.app.ActivityThread.main(ActivityThread.java:6863)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    
    
    E/P_BleManager_ListenerProcessor: MAIN(10532) onNativeBleStateChange() - 12 13 ON TURNING_OFF
    
    E/ActivityThread: Service com.android.bluetooth.avrcp.AvrcpTargetService has leaked IntentReceiver com.android.bluetooth.avrcp.AvrcpTargetService$AvrcpBroadcastReceiver@8737487 that was originally registered here. Are you missing a call to unregisterReceiver()?
        android.app.IntentReceiverLeaked: Service com.android.bluetooth.avrcp.AvrcpTargetService has leaked IntentReceiver com.android.bluetooth.avrcp.AvrcpTargetService$AvrcpBroadcastReceiver@8737487 that was originally registered here. Are you missing a call to unregisterReceiver()?
            at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1469)
            at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:1236)
            at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1479)
            at android.app.ContextImpl.registerReceiver(ContextImpl.java:1452)
            at android.app.ContextImpl.registerReceiver(ContextImpl.java:1440)
            at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:623)
            at com.android.bluetooth.avrcp.AvrcpTargetService.start(AvrcpTargetService.java:150)
            at com.android.bluetooth.btservice.ProfileService.doStart(ProfileService.java:284)
            at com.android.bluetooth.btservice.ProfileService.onStartCommand(ProfileService.java:166)
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3802)
            at android.app.ActivityThread.access$1800(ActivityThread.java:207)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1779)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:193)
            at android.app.ActivityThread.main(ActivityThread.java:6863)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    


  • Ok, thanks for the information you could provide. We'll dig into the code and try to trace it down. We'll have something in the next release to address it. Hopefully we find out why it's getting a null type, last resort is to just null check it.



  • I believe I found the culprit for this bug. The case I found was in a situation where a write is attempted, SweetBlue does it's early out check, and directly after, the device gets disconnected. Every other path I traced looked like it shouldn't create a null Type. So this should be fixed in the next release. It's hard to know 100% for sure without knowing the steps to reproduce the original issue.



  • Glad to hear! Looking forward to the next release.