Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f05d0b31 authored by Jacky Cheung's avatar Jacky Cheung
Browse files

DO NOT MERGE ANYWHERE Auto Connection Parameter Update for Whitelisted Address

Auto adjust connection interval parameter after a certain idle
period on the connection.

BUG: 32380838

Change-Id: I28cf4f6d5dcfb7a0bfb6aa652d939e16fbdcdcde
parent b162e61a
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3078,6 +3078,18 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
            btif_storage_remove_bonded_device(&bdaddr);
            state = BT_BOND_STATE_NONE;
        } else {
            /*
             * Note: This is a Wear-specific feature for iOS pairing.
             * Store the address of the first bonded device that is also of type LE to
             * enable auto connection parameter update.
             */
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
            if (btif_storage_get_num_bonded_devices() == 0) {
                bdstr_t bdstr;
                bdaddr_to_string(&bdaddr, bdstr, sizeof(bdstr));
                btif_config_set_str("Adapter", "AutoConnParamUpdateAddr", bdstr);
            }
#endif
            btif_dm_save_ble_bonding_keys();
            BTA_GATTC_Refresh(bd_addr.address);
            btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
+162 −2
Original line number Diff line number Diff line
@@ -50,8 +50,9 @@
#include "btif_gatt_multi_adv_util.h"
#include "btif_gatt_util.h"
#include "btif_storage.h"
#include "btif_storage.h"
#include "osi/include/log.h"
#include "osi/include/alarm.h"
#include "stack/include/gatt_api.h"
#include "vendor_api.h"

/*******************************************************************************
@@ -239,6 +240,133 @@ static btif_gattc_dev_cb_t btif_gattc_dev_cb;
static btif_gattc_dev_cb_t  *p_dev_cb = &btif_gattc_dev_cb;
static uint8_t rssi_request_client_if;

/*******************************************************************************
**  Auto Connection Parameter Update
**
**  Feature is enabled when WEAR_AUTO_CONN_PARAM_UPDATE build config is set to
**  TRUE.  It looks for a whitelisted address in the configuration file and
**  automatically applies a connection interval parameter update
**  (WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS) when the connection is idle for a
**  specific period of time (WEAR_AUTO_CONN_IDLE_TIMEOUT_MS).
********************************************************************************/
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
typedef struct
{
    bt_bdaddr_t device_address;
    uint16_t    min_interval;
    uint16_t    max_interval;
    uint16_t    timeout;
    uint16_t    latency;
    bool        is_auto_update_address_known;
    bool        is_auto_update_enabled;
    bool        is_updating;
    alarm_t     *check_idle_alarm;
} btgatt_auto_connection_param_update_cb_t;

static btgatt_auto_connection_param_update_cb_t auto_conn_param_update_cb;

static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
             int max_interval, int latency, int timeout);

static void auto_connection_param_update_idle_cb(UNUSED_ATTR void *data)
{
    btgatt_auto_connection_param_update_cb_t *auto_update_cb =
        (btgatt_auto_connection_param_update_cb_t *)data;

    if (auto_conn_param_update_cb.is_updating)
    {
        LOG_WARN(LOG_TAG, "%s another connection update in progress", __FUNCTION__);
        return;
    }

    btif_gattc_conn_parameter_update_internal(&auto_update_cb->device_address,
        WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, 0, 2000);
    LOG_INFO(LOG_TAG, "%s auto adjust connection interval to %dms", __FUNCTION__,
             (int)(WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS * 1.25f));
}

static void maybe_set_connection_param_update_in_progress(const bt_bdaddr_t *bd_addr, bool in_progress)
{
    if (auto_conn_param_update_cb.is_auto_update_enabled &&
        bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
    {
        auto_conn_param_update_cb.is_updating = in_progress;
    }
}

static void maybe_enable_auto_connection_param_update(const bt_bdaddr_t *bd_addr, int min_interval,
                                                      int max_interval, int latency, int timeout)
{
    /* First check if there is a whitelisted address to enable auto connection param update */
    if (!auto_conn_param_update_cb.is_auto_update_address_known)
    {
        bdstr_t bdstr;
        int bdstr_size = sizeof(bdstr);
        if (btif_config_get_str("Adapter", "AutoConnParamUpdateAddr", bdstr, &bdstr_size))
        {
            bt_bdaddr_t auto_update_addr;
            string_to_bdaddr(bdstr, &auto_update_addr);
            bdcpy(auto_conn_param_update_cb.device_address.address, auto_update_addr.address);
            LOG_INFO(LOG_TAG, "%s auto connection param update for address: %s", __FUNCTION__, bdstr);
        }
        auto_conn_param_update_cb.is_auto_update_address_known = true;
    }

    /* If the address matches the auto update address, store the connection parameter value */
    if (bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
    {
        auto_conn_param_update_cb.min_interval = min_interval;
        auto_conn_param_update_cb.max_interval = max_interval;
        auto_conn_param_update_cb.timeout = timeout;
        auto_conn_param_update_cb.latency = latency;
        auto_conn_param_update_cb.is_auto_update_enabled = true;
    }
}

static void maybe_restore_connection_parameters(BD_ADDR address) {
    /*
     * Will not perform auto connection parameter update if:
     *
     * - feature not enabled (yet)
     * - address doesn't match auto update address
     * - connection parameter update is in progress
     */
    if (!auto_conn_param_update_cb.is_auto_update_enabled ||
        (bdcmp(auto_conn_param_update_cb.device_address.address, address) != 0) ||
        auto_conn_param_update_cb.is_updating)
    {
        return;
    }

    if (alarm_is_scheduled(auto_conn_param_update_cb.check_idle_alarm))
    {
        /* Idle alarm is scheduled, reschedule it */
        alarm_cancel(auto_conn_param_update_cb.check_idle_alarm);
    }
    else
    {
        /* No idle alarm and no update in progress, restore specified connection parameters */
        btif_gattc_conn_parameter_update_internal(&auto_conn_param_update_cb.device_address,
                                                  auto_conn_param_update_cb.min_interval,
                                                  auto_conn_param_update_cb.max_interval,
                                                  auto_conn_param_update_cb.latency,
                                                  auto_conn_param_update_cb.timeout);
        LOG_VERBOSE(LOG_TAG, "%s restore connection parameters", __FUNCTION__);
    }

    /* Schedule idle alarm */
    if (!auto_conn_param_update_cb.check_idle_alarm)
    {
        auto_conn_param_update_cb.check_idle_alarm =
            alarm_new("gatt_client.auto_conn_param_update_idle_alarm");
    }
    alarm_set(auto_conn_param_update_cb.check_idle_alarm, WEAR_AUTO_CONN_IDLE_TIMEOUT_MS,
              auto_connection_param_update_idle_cb, &auto_conn_param_update_cb);

    return;
}
#endif

/*******************************************************************************
**  Static functions
********************************************************************************/
@@ -540,6 +668,10 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
            if (p_data->notify.is_notify == FALSE)
                BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);

#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
            maybe_restore_connection_parameters(data.bda.address);
#endif

            break;
        }

@@ -806,6 +938,9 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
        case BTA_GATTC_CONN_PARAM_UPD_EVT:
        {
            btif_conn_param_cb_t *p_btif_cb = (btif_conn_param_cb_t *)p_param;
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
            maybe_set_connection_param_update_in_progress(&p_btif_cb->bd_addr, false);
#endif
            /* Log update failures */
            if (p_btif_cb->status != 0)
            {
@@ -1283,9 +1418,21 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
            break;

        case BTIF_GATTC_WRITE_CHAR:
        {
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
            /* TODO(jackyc): find a cleaner way to get address from connection id */
            tGATT_IF gatt_if;
            BD_ADDR bd_addr;
            tBT_TRANSPORT transport;
            if (GATT_GetConnectionInfor(p_cb->conn_id, &gatt_if, bd_addr, &transport) == TRUE)
            {
                maybe_restore_connection_parameters(bd_addr);
            }
#endif
            BTA_GATTC_WriteCharValue(p_cb->conn_id, p_cb->handle, p_cb->write_type,
                                     p_cb->len, p_cb->value, p_cb->auth_req);
            break;
        }

        case BTIF_GATTC_WRITE_CHAR_DESCR:
            descr_val.len = p_cb->len;
@@ -1905,10 +2052,13 @@ static bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu)
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}

static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
                                                    int max_interval, int latency, int timeout)
{
    CHECK_BTGATT_INIT();
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
    maybe_set_connection_param_update_in_progress(bd_addr, true);
#endif
    btif_conn_param_cb_t btif_cb;
    btif_cb.requested_min_interval = min_interval;
    btif_cb.requested_max_interval = max_interval;
@@ -1919,6 +2069,16 @@ static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr,
                                 (char*) &btif_cb, sizeof(btif_conn_param_cb_t), NULL);
}

static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
                                                    int max_interval, int latency, int timeout)
{
#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
    maybe_enable_auto_connection_param_update(bd_addr, min_interval, max_interval, latency, timeout);
#endif

    return btif_gattc_conn_parameter_update_internal(bd_addr, min_interval, max_interval, latency, timeout);
}

static bt_status_t btif_gattc_scan_filter_param_setup(btgatt_filt_param_setup_t
                                                      filt_param)
{
+27 −1
Original line number Diff line number Diff line
@@ -1566,4 +1566,30 @@ The maximum number of payload octets that the local device can receive in a sing
#define WEAR_LE_IO_CAP_OVERRIDE               FALSE
#endif

/*
 * Enable/disable LE auto connection parameter update.
 * When enabled, the first bonded device that is also of type LE will be whitelisted
 * to use auto connection parameter update.
 */
#ifndef WEAR_AUTO_CONN_PARAM_UPDATE
#define WEAR_AUTO_CONN_PARAM_UPDATE           FALSE
#endif

/*
 * Idle timeout period in milliseconds for auto connection parameter update.
 * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
 */
#ifndef WEAR_AUTO_CONN_IDLE_TIMEOUT_MS
#define WEAR_AUTO_CONN_IDLE_TIMEOUT_MS        10000
#endif

/*
 * Connection interval parameter applied when the connection is detected to be idle for
 * WEAR_AUTO_CONN_IDLE_TIMEOUT_MS of time.
 * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
 */
#ifndef WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS
#define WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS  72
#endif

#endif /* BT_TARGET_H */