bluetooth: host: Do not send unwanted SC indicate

Fixes #23485

When we create a GATT table dynamically, we also create a hash
identifying this table. This hash can be stored in persistent memory and
we can thus determine after recreating the GATT table whether the
services have changed or not from before the reboot.

When these hashes are identical, it implies that the table has not
changed, wherefore a service changed indication should not be sent to
any bonded clients. The method for achieving this was to remove the
gatt_sc.work entry from the work queue. This work queue entry was to
send an indication to the clients when the table had been allocated.
If the final entry then caused the hashes to match, the indication
would be cancelled.

On unit testing this behaviour in simulation and in practice, we found
that the indication was sent nonetheless, and the issue was located to
be tied to the SERVICE_RANGE_CHANGED flag which is set when the services
are changed and is cleared when the indications are being sent out.

It was the job of the work queue entry to clear this flag, and as the
entry was never serviced, the flag was never cleared, and when
sc_commit() is called at the end of the process, it believes that there
is a new service change pending and therefore starts the job over, thus
creating a redundant indication to the clients.

This commit fixes the issue by clearing the flag when the work entry
is removed due to a hash match. This has been unittested in a live
environment, in a simulation environment, and sanitycheck has been run
on it.

Signed-off-by: Dan Erichsen <daee@demant.com>
This commit is contained in:
Dan Erichsen 2020-03-13 16:45:35 +01:00 committed by Johan Hedberg
commit 6a12a2dbe1

View file

@ -4358,6 +4358,7 @@ static int db_hash_commit(void)
if (!memcmp(stored_hash, db_hash, sizeof(stored_hash))) {
BT_DBG("Database Hash matches");
k_delayed_work_cancel(&gatt_sc.work);
atomic_clear_bit(gatt_sc.flags, SC_RANGE_CHANGED);
return 0;
}