Disconnect when connected to a Bluetooth low energy (BLE) device

I am currently running a pairing routine (well, when it starts automatically, to be honest) when I try to perform a GATT operation and it fails to complete the operation successfully. Once the pairing procedure is done and I get a connection with the remote device, I continue to do my GATT operations in which everything works fine.

I noticed that when pairing:

1) if I disconnect from the remote device without closing the GATT client, it still connects successfully and I enter the state BluetoothDevice.BOND_BONDED

and my application continues to work fine.
2) if I disconnect and I also close the GATT client and then when I enter the state BluetoothDevice.BOND_BONDED

then my application crashes

Why does my application crash when I close the GATT client of the remote device during the pairing procedure? is this ok or am I doing something wrong?

This is my BroadcastReceiver implementation for getting the connection state of a remote device.

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
            final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);

            if(state == BluetoothDevice.BOND_BONDING){
                DebugWrapper.debugMsg("On Bonding...", TAG);
                mIsBonding = true;
                onBonding();
            } else if(state == BluetoothDevice.BOND_BONDED){
                DebugWrapper.debugMsg("On Bonded", TAG);
                mIsBonded = true;

                    mActivity.unregisterReceiver(mReceiver);

                    /*
                     * finish what we started
                     */
                    if(mBluetoothGatt != null){

                        if(mOperationState == OperationState.READ_CHARACTERISTIC){
                            readCharacteristic(mCurrentCharacteristic);
                        } else if(mOperationState == OperationState.WRITE_CHARACTERISTIC){
                            writeCharacteristic(mCurrentCharacteristic);
                        } else if(mOperationState == OperationState.READ_DESCRIPTOR){
                            readDescriptor(mCurrentDescriptor);
                        } else if(mOperationState == OperationState.WRITE_DESCRIPTOR){
                            writeDescriptor(mCurrentDescriptor);
                        }
                        mOperationState = OperationState.NONE;
                    }

                    onBonded();

            } else if(state == BluetoothDevice.BOND_NONE){
                DebugWrapper.debugMsg("Not Bonded", TAG);
                notBonded();
            }
        }
    }
};

      

Update LogCat files (links to Pastebin.com as files where too big to add here)

From this logCat you can see the steps I am following

LogCat application complete

+3


source to share


1 answer


You seem to have found a bug in bluedroid, Android bluetooth stack.

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), error addr 00000008

backtrace:
#00  pc 0007c86e /system/lib/hw/bluetooth.default.so (GKI_getnext+9)
#01  pc 000bd9e3  /system/lib/hw/bluetooth.default.so (gatt_sec_check_complete+10)
#02  pc 000bdde9  /system/lib/hw/bluetooth.default.so (gatt_enc_cmpl_cback+104)

      

This is the original null pointer exception in gki / common / gki_buffer.c of the BT "bluedroid" Android stack.

This is a confusion , since at first glance the problematic function looks like GKI_getnext (), but in fact it is actually the first instruction of the immediately following function GKI_queue_is_empty ()

BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
{
    return ((BOOLEAN) (p_q->count == 0));
}

      

If we look at the actual decompilation,



<GKI_queue_is_empty>:
    ldrh    r0, [r0, #8]
    rsbs    r0, r0, #1
    it      cc
    movcc   r0, #0
    bx      lr

      

We can see that we are trying to reference the count

structure member BUFFER_Q

pointed to by r0, however what happens is that we were called with a NULL buffer, so we add 8 to NULL and try to load the register from the illegal address 00000008

that calls SIGSEGV.

Going up the level, this is called from gatt_sec_check_complete () - indeed, if we look in stack / gatt / gatt_auth.c , we find that this is the first is is check if the queue is empty.

void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB   *p_clcb, UINT8 sec_act)
{
    if (GKI_queue_is_empty(&p_clcb->p_tcb->pending_enc_clcb))
        gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);

      

But the problem is that the queue is not empty, but it is null .

So, there is either a bug in bluedroid where it doesn't understand that something could be NULL, or your program generates an invalid sequence of operations that sets up the bluedroid stack for this failure.

The assignment of guilt, however, turns out to be simple because we can look at the security model. The process crashes as a user bluetooth

, which is a semi-privileged account and not your application's user ID. So, as a basic principle, nothing your unprivileged application should be able to crash it , and we can classify this as a bug in the bluetooth stack of the platform, not your application.

+2


source







All Articles