From 02b292f01c5321507f11d039007e5df569ca1015 Mon Sep 17 00:00:00 2001 From: Mingbo <quic_mingboz@quicinc.com> Date: Thu, 12 Jan 2023 10:17:52 +0000 Subject: [PATCH] device_iot_config: store iot device info Store remote basic info (e.g. name, dev class, dev type, etc.) and profile info (a2dp/hfp/avrcp/gap) to local conf file. Snapshot as of: 43ab2ffdf6bdc48d0fb4a4d715da8863599f24e0 e080af8694d274d5db20204c48b9f6b714b17498 48b1654da46649a01ee9ab422f20aa60b8b31efd 964e674a41dbfdea612c66c684abc4d0e27500c1 Sponsor: narajn@ Bug: 261319328 Tag: #feature Test: atest bluetooth_test_gd BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines Change-Id: If4c2632d3874fbec1e3477f40cd11b4b1db7a118 --- system/bta/Android.bp | 1 + system/bta/ag/bta_ag_act.cc | 23 +- system/bta/av/bta_av_aact.cc | 16 +- system/bta/av/bta_av_act.cc | 52 ++- system/bta/dm/bta_dm_act.cc | 2 +- system/btif/Android.bp | 3 + system/btif/BUILD.gn | 1 + system/btif/co/bta_av_co.cc | 22 +- system/btif/src/bluetooth.cc | 15 +- system/btif/src/btif_av.cc | 21 + system/btif/src/btif_core.cc | 5 + system/btif/src/btif_dm.cc | 6 + system/btif/src/btif_hf.cc | 40 ++ system/btif/src/btif_iot_config.cc | 149 +++++++ system/btif/src/stack_manager.cc | 8 +- system/device/Android.bp | 2 + system/device/BUILD.gn | 2 + system/device/include/device_iot_conf_defs.h | 109 +++++ system/device/include/device_iot_config.h | 105 +++++ system/device/src/device_iot_config.cc | 379 ++++++++++++++++++ system/device/src/device_iot_config_int.cc | 331 +++++++++++++++ system/device/src/device_iot_config_int.h | 97 +++++ system/stack/Android.bp | 6 + system/stack/BUILD.gn | 1 + system/stack/a2dp/a2dp_codec_config.cc | 39 ++ system/stack/acl/btm_acl.cc | 30 ++ system/stack/avct/avct_lcb.cc | 5 + system/stack/avct/avct_lcb_act.cc | 7 + system/stack/btm/btm_ble.cc | 32 +- system/stack/btm/btm_iot_config.cc | 95 +++++ system/stack/btm/btm_sco.cc | 9 +- system/stack/btm/btm_sec.cc | 5 + system/stack/hcic/hcicmds.cc | 2 + system/stack/include/a2dp_codec_api.h | 4 + system/stack/include/btm_ble_api.h | 12 + system/stack/l2cap/l2c_link.cc | 33 ++ system/stack/test/btm/stack_btm_test.cc | 1 + system/stack/test/stack_acl_test.cc | 1 + .../test/mock/mock_stack_a2dp_codec_config.cc | 4 + system/test/mock/mock_stack_btm_ble.cc | 6 + system/test/mock/mock_stack_btm_ble.h | 13 + 41 files changed, 1681 insertions(+), 13 deletions(-) create mode 100644 system/btif/src/btif_iot_config.cc create mode 100644 system/device/include/device_iot_conf_defs.h create mode 100644 system/device/include/device_iot_config.h create mode 100644 system/device/src/device_iot_config.cc create mode 100644 system/device/src/device_iot_config_int.cc create mode 100644 system/device/src/device_iot_config_int.h create mode 100644 system/stack/btm/btm_iot_config.cc diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 18a6cc1260e..eb9f953751d 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -295,6 +295,7 @@ cc_test { ], static_libs: [ "libbluetooth-types", + "libbtdevice", "libbt-common", "libbt-protos-lite", "libbtcore", diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc index fef362082c5..2612f48bcc0 100644 --- a/system/bta/ag/bta_ag_act.cc +++ b/system/bta/ag/bta_ag_act.cc @@ -22,19 +22,20 @@ * ******************************************************************************/ +#include <base/logging.h> + #include <cstdint> #include <cstring> #include "bta/ag/bta_ag_int.h" #include "bta/include/bta_dm_api.h" #include "btif/include/btif_config.h" +#include "device/include/device_iot_config.h" #include "osi/include/osi.h" // UNUSED_ATTR #include "stack/include/l2c_api.h" #include "stack/include/port_api.h" #include "types/raw_address.h" -#include <base/logging.h> - /***************************************************************************** * Constants ****************************************************************************/ @@ -222,6 +223,10 @@ void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { /* send ourselves sdp ok event */ event = BTA_AG_DISC_OK_EVT; + + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER( + p_scb->peer_addr, IOT_CONF_KEY_HFP_VERSION, p_scb->peer_version, + IOT_CONF_BYTE_NUM_2); } } @@ -269,6 +274,9 @@ void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { data.disc_result.status == SDP_DB_FULL) { /* get attributes */ bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]); + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER( + p_scb->peer_addr, IOT_CONF_KEY_HFP_VERSION, p_scb->peer_version, + IOT_CONF_BYTE_NUM_2); } /* free discovery db */ @@ -520,6 +528,7 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { /* get bd addr of peer */ uint16_t lcid = 0; + uint16_t hfp_version = 0; RawAddress dev_addr = RawAddress::kEmpty; int status = PORT_CheckConnection(data.rfc.port_handle, &dev_addr, &lcid); if (status != PORT_SUCCESS) { @@ -583,6 +592,16 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { bta_ag_close_servers( p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service])); + size_t version_value_size = sizeof(hfp_version); + bool get_version = + btif_config_get_bin(p_scb->peer_addr.ToString(), HFP_VERSION_CONFIG_KEY, + (uint8_t*)&hfp_version, &version_value_size); + + if (p_scb->conn_service == BTA_AG_HFP && get_version) { + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER(p_scb->peer_addr, + IOT_CONF_KEY_HFP_VERSION, + hfp_version, IOT_CONF_BYTE_NUM_2); + } /* do service discovery to get features */ bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]); diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index 0e1d8746c16..83aca43b861 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -40,6 +40,7 @@ #include "btif/include/btif_av_co.h" #include "btif/include/btif_config.h" #include "btif/include/btif_storage.h" +#include "device/include/device_iot_config.h" #include "device/include/interop.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" @@ -533,6 +534,10 @@ static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service, } if (found && (p_service != NULL)) { p_scb->SetAvdtpVersion(p_service->avdt_version); + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER( + p_scb->PeerAddress(), IOT_CONF_KEY_A2DP_VERSION, + p_service->avdt_version, IOT_CONF_BYTE_NUM_2); + if (p_service->avdt_version != 0) { if (btif_config_set_bin(p_scb->PeerAddress().ToString(), AVDTP_VERSION_CONFIG_KEY, @@ -970,10 +975,17 @@ void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { p_info->seid = p_data->str_msg.msg.config_ind.int_seid; /* Sep type of Peer will be oppsite role to our local sep */ - if (local_sep == AVDT_TSEP_SRC) + if (local_sep == AVDT_TSEP_SRC) { p_info->tsep = AVDT_TSEP_SNK; - else if (local_sep == AVDT_TSEP_SNK) + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_scb->PeerAddress(), + IOT_CONF_KEY_A2DP_ROLE, + IOT_CONF_VAL_A2DP_ROLE_SINK); + } else if (local_sep == AVDT_TSEP_SNK) { p_info->tsep = AVDT_TSEP_SRC; + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_scb->PeerAddress(), + IOT_CONF_KEY_A2DP_ROLE, + IOT_CONF_VAL_A2DP_ROLE_SOURCE); + } p_scb->role |= BTA_AV_ROLE_AD_ACP; p_scb->cur_psc_mask = p_evt_cfg->psc_mask; diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc index ec6d3b7bc35..2eb93c612cf 100644 --- a/system/bta/av/bta_av_act.cc +++ b/system/bta/av/bta_av_act.cc @@ -32,6 +32,7 @@ #include "bta/include/bta_ar_api.h" #include "bta/include/utl.h" #include "btif/avrcp/avrcp_service.h" +#include "device/include/device_iot_config.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "osi/include/osi.h" // UNUSED_ATTR @@ -323,6 +324,9 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, tBTA_AV_SCB* p_scb = p_cb->p_scb[shdl - 1]; bda = p_scb->PeerAddress(); status = BTA_AV_RC_ROLE_INT; + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_scb->PeerAddress(), + IOT_CONF_KEY_AVRCP_CONN_COUNT); + } else { p_rcb = bta_av_get_rcb_by_shdl(shdl); if (p_rcb != NULL) { @@ -341,8 +345,10 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA | AVRC_CT_PASSIVE); - if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS) + if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS) { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(bda, IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT); return BTA_AV_RC_HANDLE_NONE; + } i = rc_handle; p_rcb = &p_cb->rcb[i]; @@ -1650,6 +1656,39 @@ static void bta_av_accept_signalling_timer_cback(void* data) { } } +static void bta_av_store_peer_rc_version() { + tBTA_AV_CB* p_cb = &bta_av_cb; + tSDP_DISC_REC* p_rec = NULL; + uint16_t peer_rc_version = 0; /*Assuming Default peer version as 1.3*/ + + if ((p_rec = SDP_FindServiceInDb( + p_cb->p_disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL)) != NULL) { + if ((SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL) { + /* get profile version (if failure, version parameter is not updated) */ + SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, + &peer_rc_version); + } + if (peer_rc_version != 0) + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER( + p_rec->remote_bd_addr, IOT_CONF_KEY_AVRCP_CTRL_VERSION, + peer_rc_version, IOT_CONF_BYTE_NUM_2); + } + + peer_rc_version = 0; + if ((p_rec = SDP_FindServiceInDb( + p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, NULL)) != NULL) { + if ((SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL) { + /* get profile version (if failure, version parameter is not updated) */ + SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, + &peer_rc_version); + } + if (peer_rc_version != 0) + DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER( + p_rec->remote_bd_addr, IOT_CONF_KEY_AVRCP_TG_VERSION, peer_rc_version, + IOT_CONF_BYTE_NUM_2); + } +} + /******************************************************************************* * * Function bta_av_check_peer_features @@ -1986,6 +2025,8 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) { } } + bta_av_store_peer_rc_version(); + p_cb->disc = 0; osi_free_and_reset((void**)&p_cb->p_disc_db); @@ -2036,6 +2077,10 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) { bta_av_data.rc_open = rc_open; (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, &bta_av_data); } + if (peer_features != 0) + DEVICE_IOT_CONFIG_ADDR_SET_HEX(p_scb->PeerAddress(), + IOT_CONF_KEY_AVRCP_FEATURES, + peer_features, IOT_CONF_BYTE_NUM_2); } } else { tBTA_AV_RC_FEAT rc_feat; @@ -2057,6 +2102,11 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) { bta_av_feat.rc_feat = rc_feat; (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, &bta_av_feat); + if (peer_features != 0) + DEVICE_IOT_CONFIG_ADDR_SET_HEX(rc_feat.peer_addr, + IOT_CONF_KEY_AVRCP_FEATURES, peer_features, + IOT_CONF_BYTE_NUM_2); + // Send PSM data APPL_TRACE_DEBUG("%s: Send PSM data", __func__); tBTA_AV_RC_PSM rc_psm; diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index cfb87b39644..69a334ba440 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -59,7 +59,7 @@ #include "stack/include/bt_octets.h" #include "stack/include/bt_types.h" #include "stack/include/btm_client_interface.h" -#include "stack/include/btu.h" // do_in_main_thread +#include "stack/include/btu.h" // do_in_main_thread #include "stack/include/srvc_api.h" // DIS_ReadDISInfo #include "types/bluetooth/uuid.h" #include "types/raw_address.h" diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 6fca3df1b05..81e517744b8 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -115,6 +115,7 @@ cc_library_static { "src/btif_hf_client.cc", "src/btif_hh.cc", "src/btif_hd.cc", + "src/btif_iot_config.cc", "src/btif_le_audio.cc", "src/btif_le_audio_broadcaster.cc", "src/btif_pan.cc", @@ -186,6 +187,7 @@ cc_library_static { "src/btif_gatt_server.cc", "src/btif_gatt_test.cc", "src/btif_gatt_util.cc", + "src/btif_iot_config.cc", "src/btif_metrics_logging.cc", "src/btif_profile_queue.cc", "src/btif_sdp.cc", @@ -658,6 +660,7 @@ cc_test { "libbt-sbc-encoder", "libbtif", "libbtif-core", + "libbt-stack-core", "libbtdevice", "lib-bt-packets", "lib-bt-packets-avrcp", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 814c911dde8..625157e45ab 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -71,6 +71,7 @@ static_library("btif") { "src/btif_hf.cc", "src/btif_hf_client.cc", "src/btif_hh.cc", + "src/btif_iot_config.cc", "src/btif_keystore.cc", "src/btif_le_audio.cc", "src/btif_metrics_logging.cc", diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index 653b201a35e..426bdc7e519 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -23,6 +23,8 @@ * ******************************************************************************/ +#include <base/logging.h> + #include <mutex> #include <vector> @@ -31,6 +33,7 @@ #include "bta/include/bta_av_ci.h" #include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_av.h" +#include "device/include/device_iot_config.h" #include "include/hardware/bt_av.h" #include "osi/include/osi.h" // UNUSED_ATTR #include "stack/include/a2dp_codec_api.h" @@ -40,8 +43,6 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -#include <base/logging.h> - // Macro to retrieve the number of elements in a statically allocated array #define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0])) @@ -910,6 +911,8 @@ void BtaAvCo::ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle, } } +static void bta_av_co_store_peer_codectype(const BtaAvCoPeer* p_peer); + tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig( tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address, uint8_t* p_codec_info, uint8_t* p_sep_info_idx, uint8_t seid, @@ -968,6 +971,8 @@ tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig( __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), p_peer->acceptor ? "acceptor" : "initiator"); + bta_av_co_store_peer_codectype(p_peer); + // Select the Source codec const BtaAvCoSep* p_sink = nullptr; if (p_peer->acceptor) { @@ -2115,6 +2120,19 @@ void bta_av_co_audio_disc_res(tBTA_AV_HNDL bta_av_handle, num_sinks, num_sources, uuid_local); } +static void bta_av_co_store_peer_codectype(const BtaAvCoPeer* p_peer) { + int index, peer_codec_type = 0; + const BtaAvCoSep* p_sink; + APPL_TRACE_DEBUG("%s", __func__); + for (index = 0; index < p_peer->num_sup_sinks; index++) { + p_sink = &p_peer->sinks[index]; + peer_codec_type |= A2DP_IotGetPeerSinkCodecType(p_sink->codec_caps); + } + + DEVICE_IOT_CONFIG_ADDR_SET_HEX(p_peer->addr, IOT_CONF_KEY_A2DP_CODECTYPE, + peer_codec_type, IOT_CONF_BYTE_NUM_1); +} + tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address, uint8_t* p_codec_info, diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index b303c3d095c..1ed5550544d 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -82,6 +82,7 @@ #include "common/metric_id_allocator.h" #include "common/metrics.h" #include "common/os_utils.h" +#include "device/include/device_iot_config.h" #include "device/include/interop.h" #include "gd/common/init_flags.h" #include "gd/os/parameter_provider.h" @@ -760,6 +761,7 @@ static void dump(int fd, const char** arguments) { stack_debug_avdtp_api_dump(fd); bluetooth::avrcp::AvrcpService::DebugDump(fd); btif_debug_config_dump(fd); + device_debug_iot_config_dump(fd); BTA_HfClientDumpStatistics(fd); wakelock_debug_dump(fd); osi_allocator_debug_dump(fd); @@ -940,7 +942,18 @@ static int set_os_callouts(bt_os_callouts_t* callouts) { static int config_clear(void) { LOG_INFO("%s", __func__); - return btif_config_clear() ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; + int ret = BT_STATUS_SUCCESS; + if (!btif_config_clear()) { + LOG_ERROR("Failed to clear btif config"); + ret = BT_STATUS_FAIL; + } + + if (!device_iot_config_clear()) { + LOG_ERROR("Failed to clear device iot config"); + ret = BT_STATUS_FAIL; + } + + return ret; } static bluetooth::avrcp::ServiceInterface* get_avrcp_service(void) { diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index e3c65b7c53c..fad4b2766dd 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -48,6 +48,7 @@ #include "btif_metrics_logging.h" #include "common/metrics.h" #include "common/state_machine.h" +#include "device/include/device_iot_config.h" #include "hardware/bt_av.h" #include "include/hardware/bt_rc.h" #include "main/shim/dumpsys.h" @@ -1502,6 +1503,18 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { BTA_AvOpen(peer_.PeerAddress(), peer_.BtaHandle(), true, peer_.LocalUuidServiceClass()); peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpening); + if (event == BTIF_AV_CONNECT_REQ_EVT) { + DEVICE_IOT_CONFIG_ADDR_SET_INT( + peer_.PeerAddress(), IOT_CONF_KEY_A2DP_ROLE, + (peer_.LocalUuidServiceClass() == UUID_SERVCLASS_AUDIO_SOURCE) + ? IOT_CONF_VAL_A2DP_ROLE_SINK + : IOT_CONF_VAL_A2DP_ROLE_SOURCE); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_COUNT); + } else if (event == BTA_AV_PENDING_EVT) { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_COUNT); + } } break; case BTIF_AV_AVRCP_OPEN_EVT: case BTA_AV_RC_OPEN_EVT: { @@ -1626,6 +1639,8 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { BTAV_CONNECTION_STATE_DISCONNECTED, bt_status_t::BT_STATUS_FAIL, status); peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT); } btif_queue_advance(); } break; @@ -1771,6 +1786,8 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, if (peer_handle != BTRC_HANDLE_NONE) { BTA_AvCloseRc(peer_handle); } + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT); } av_state = BtifAvStateMachine::kStateIdle; // Report the connection state to the application @@ -1855,6 +1872,8 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); log_counter_metrics_btif( android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_CLOSE, 1); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT); if (peer_.SelfInitiatedConnection()) { btif_queue_advance(); } @@ -1866,6 +1885,8 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, BTAV_CONNECTION_STATE_DISCONNECTED, bt_status_t::BT_STATUS_FAIL, BTA_AV_FAIL); peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), + IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT); log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum:: A2DP_CONNECTION_DISCONNECTED, 1); diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 7803b9550a1..50634ec7564 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -50,6 +50,7 @@ #include "btif/include/stack_manager.h" #include "common/message_loop_thread.h" #include "device/include/controller.h" +#include "device/include/device_iot_config.h" #include "osi/include/allocator.h" #include "osi/include/future.h" #include "osi/include/log.h" @@ -271,6 +272,10 @@ void btif_enable_bluetooth_evt() { std::string bdstr = local_bd_addr.ToString(); + // save bd addr to iot conf file + device_iot_config_set_str(IOT_CONF_KEY_SECTION_ADAPTER, IOT_CONF_KEY_ADDRESS, + bdstr); + char val[PROPERTY_VALUE_MAX] = ""; int val_size = PROPERTY_VALUE_MAX; if (!btif_config_get_str("Adapter", "Address", val, &val_size) || diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 921ecaea6f5..d2f65b4a3d7 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -70,6 +70,7 @@ #include "common/lru.h" #include "common/metrics.h" #include "device/include/controller.h" +#include "device/include/device_iot_config.h" #include "device/include/interop.h" #include "gd/common/lru_cache.h" #include "internal_include/stack_config.h" @@ -278,6 +279,8 @@ static void btif_stats_add_bond_event(const RawAddress& bd_addr, * Externs *****************************************************************************/ extern bt_status_t btif_sdp_execute_service(bool b_enable); +extern void btif_iot_update_remote_info(tBTA_DM_AUTH_CMPL* p_auth_cmpl, + bool is_ble, bool is_ssp); /****************************************************************************** * Functions @@ -1044,6 +1047,9 @@ static void btif_dm_auth_cmpl_evt(tBTA_DM_AUTH_CMPL* p_auth_cmpl) { } if (p_auth_cmpl->success) { + // save remote info to iot conf file + btif_iot_update_remote_info(p_auth_cmpl, false, pairing_cb.is_ssp); + // We could have received a new link key without going through the pairing // flow. If so, we don't want to perform SDP or any other operations on the // authenticated device. Also, make sure that the link key is not derived diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 9aa2d3e30cd..cae17411318 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -40,6 +40,7 @@ #include "btif/include/btif_profile_queue.h" #include "btif/include/btif_util.h" #include "common/metrics.h" +#include "device/include/device_iot_config.h" #include "include/hardware/bluetooth_headset_callbacks.h" #include "include/hardware/bluetooth_headset_interface.h" #include "include/hardware/bt_hf.h" @@ -388,6 +389,14 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { if (p_data->open.status == BTA_AG_SUCCESS) { // In case this is an incoming connection btif_hf_cb[idx].connected_bda = p_data->open.bd_addr; + if (btif_hf_cb[idx].state != BTHF_CONNECTION_STATE_CONNECTING) { + DEVICE_IOT_CONFIG_ADDR_SET_INT(btif_hf_cb[idx].connected_bda, + IOT_CONF_KEY_HFP_ROLE, + IOT_CONF_VAL_HFP_ROLE_CLIENT); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(btif_hf_cb[idx].connected_bda, + IOT_CONF_KEY_HFP_SLC_CONN_COUNT); + } + btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED; btif_hf_cb[idx].peer_feat = 0; clear_phone_state_multihf(&btif_hf_cb[idx]); @@ -414,6 +423,8 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { HFP_SELF_INITIATED_AG_FAILED, 1); btif_queue_advance(); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE( + connected_bda, IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT); } break; case BTA_AG_CLOSE_EVT: { @@ -439,10 +450,22 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { android::bluetooth::CodePathCounterKeyEnum::HFP_SLC_SETUP_FAILED, 1); btif_queue_advance(); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE( + btif_hf_cb[idx].connected_bda, + IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT); } break; } case BTA_AG_CONN_EVT: + DEVICE_IOT_CONFIG_ADDR_SET_HEX( + btif_hf_cb[idx].connected_bda, IOT_CONF_KEY_HFP_CODECTYPE, + p_data->conn.peer_codec == 0x03 ? IOT_CONF_VAL_HFP_CODECTYPE_CVSDMSBC + : IOT_CONF_VAL_HFP_CODECTYPE_CVSD, + IOT_CONF_BYTE_NUM_1); + DEVICE_IOT_CONFIG_ADDR_SET_HEX( + btif_hf_cb[idx].connected_bda, IOT_CONF_KEY_HFP_FEATURES, + p_data->conn.peer_feat, IOT_CONF_BYTE_NUM_2); + LOG_DEBUG("SLC connected event:%s idx:%d", dump_hf_event(event), idx); btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat; btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED; @@ -461,6 +484,10 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { case BTA_AG_AUDIO_CLOSE_EVT: LOG_DEBUG("Audio close event:%s", dump_hf_event(event)); + + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(btif_hf_cb[idx].connected_bda, + IOT_CONF_KEY_HFP_SCO_CONN_FAIL_COUNT); + bt_hf_callbacks->AudioStateCallback(BTHF_AUDIO_STATE_DISCONNECTED, &btif_hf_cb[idx].connected_bda); break; @@ -702,6 +729,11 @@ static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) { hf_cb->is_initiator = true; hf_cb->peer_feat = 0; BTA_AgOpen(hf_cb->handle, hf_cb->connected_bda); + + DEVICE_IOT_CONFIG_ADDR_SET_INT(hf_cb->connected_bda, IOT_CONF_KEY_HFP_ROLE, + IOT_CONF_VAL_HFP_ROLE_CLIENT); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(hf_cb->connected_bda, + IOT_CONF_KEY_HFP_SLC_CONN_COUNT); return BT_STATUS_SUCCESS; } @@ -854,6 +886,9 @@ bt_status_t HeadsetInterface::ConnectAudio(RawAddress* bd_addr, BTHF_AUDIO_STATE_CONNECTING, &btif_hf_cb[idx].connected_bda)); BTA_AgAudioOpen(btif_hf_cb[idx].handle, force_cvsd); + + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(*bd_addr, IOT_CONF_KEY_HFP_SCO_CONN_COUNT); + return BT_STATUS_SUCCESS; } @@ -1157,6 +1192,7 @@ bt_status_t HeadsetInterface::PhoneStateChange( LOG_WARN("Invalid index %d for %s", idx, PRIVATE_ADDRESS(raw_address)); return BT_STATUS_FAIL; } + const btif_hf_cb_t& control_block = btif_hf_cb[idx]; if (!IsSlcConnected(bd_addr)) { LOG(WARNING) << ": SLC not connected for " << *bd_addr; @@ -1425,6 +1461,10 @@ bt_status_t HeadsetInterface::PhoneStateChange( } UpdateCallStates(&btif_hf_cb[idx], num_active, num_held, call_setup_state); + + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(btif_hf_cb[idx].connected_bda, + IOT_CONF_KEY_HFP_SCO_CONN_COUNT); + return status; } diff --git a/system/btif/src/btif_iot_config.cc b/system/btif/src/btif_iot_config.cc new file mode 100644 index 00000000000..a44794040fd --- /dev/null +++ b/system/btif/src/btif_iot_config.cc @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include "bt_target.h" +#include "bta_api.h" +#include "btif_storage.h" +#include "device/include/device_iot_config.h" +#include "stack/include/btm_ble_api.h" + +/******************************************************************************* + * Constants & Macros + ******************************************************************************/ +#define COD_UNCLASSIFIED ((0x1F) << 8) + +/******************************************************************************* + * + * Function btif_iot_save_pair_type + * + * Description Store remote pair type to iot conf file + * + * Returns void + * + *******************************************************************************/ +static void btif_iot_save_pair_type(const RawAddress& bdaddr, bool is_ble, + bool is_ssp) { + if (is_ssp) { + if (!is_ble) + DEVICE_IOT_CONFIG_ADDR_SET_INT(bdaddr, IOT_CONF_KEY_PAIRTYPE, + IOT_CONF_VAL_PAIR_TYPE_SSP); + else + DEVICE_IOT_CONFIG_ADDR_SET_INT(bdaddr, IOT_CONF_KEY_LE_PAIRTYPE, + IOT_CONF_VAL_LE_PAIRTYPE_SECURE); + } else { + if (!is_ble) + DEVICE_IOT_CONFIG_ADDR_SET_INT(bdaddr, IOT_CONF_KEY_PAIRTYPE, + IOT_CONF_VAL_PAIR_TYPE_LEGACY); + else + DEVICE_IOT_CONFIG_ADDR_SET_INT(bdaddr, IOT_CONF_KEY_LE_PAIRTYPE, + IOT_CONF_VAL_LE_PAIRTYPE_LEGACY); + } +} + +/******************************************************************************* + * + * Function btif_iot_update_remote_info + * + * Description Store remote dev info to iot conf file + * + * Returns void + * + *******************************************************************************/ +void btif_iot_update_remote_info(tBTA_DM_AUTH_CMPL* p_auth_cmpl, bool is_ble, + bool is_ssp) { + int name_length = 0; + char value[1024]; + BD_NAME bd_name; + int num_properties = 0; + bt_property_t properties[2]; + uint32_t cod = 0; + uint8_t lmp_ver = 0; + uint16_t lmp_subver = 0; + uint16_t mfct_set = 0; + tBTM_STATUS btm_status; + + // save remote name to iot conf file + if (strlen((const char*)p_auth_cmpl->bd_name)) { + name_length = strlen((char*)p_auth_cmpl->bd_name) > BTM_MAX_LOC_BD_NAME_LEN + ? BTM_MAX_LOC_BD_NAME_LEN + : strlen((char*)p_auth_cmpl->bd_name) + 1; + strncpy(value, (char*)p_auth_cmpl->bd_name, name_length); + DEVICE_IOT_CONFIG_ADDR_SET_STR(p_auth_cmpl->bd_addr, + IOT_CONF_KEY_REMOTE_NAME, value); + } else { + if (BTM_GetRemoteDeviceName(p_auth_cmpl->bd_addr, bd_name)) { + DEVICE_IOT_CONFIG_ADDR_SET_STR(p_auth_cmpl->bd_addr, + IOT_CONF_KEY_REMOTE_NAME, (char*)bd_name); + } + } + + // save remote dev class to iot conf file + // Try to retrieve cod from storage + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); + if (btif_storage_get_remote_device_property(&p_auth_cmpl->bd_addr, + &properties[num_properties]) == + BT_STATUS_SUCCESS) + BTIF_TRACE_DEBUG("%s cod retrieved from storage is 0x%06x", __func__, cod); + if (cod == 0) { + BTIF_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__); + cod = COD_UNCLASSIFIED; + } + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, IOT_CONF_KEY_DEVCLASS, + (int)cod); + num_properties++; + + // save remote dev type to iot conf file + bt_device_type_t dev_type; + uint8_t remote_dev_type; + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_TYPE_OF_DEVICE, sizeof(uint8_t), + &remote_dev_type); + if (btif_storage_get_remote_device_property(&p_auth_cmpl->bd_addr, + &properties[num_properties]) == + BT_STATUS_SUCCESS) { + BTIF_TRACE_DEBUG("%s retrieve dev type from storage", __func__); + dev_type = (bt_device_type_t)(remote_dev_type | p_auth_cmpl->dev_type); + } else { + dev_type = (bt_device_type_t)(p_auth_cmpl->dev_type); + } + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, IOT_CONF_KEY_DEVTYPE, + (int)dev_type); + + // save remote addr type to iot conf file + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, IOT_CONF_KEY_ADDRTYPE, + (int)p_auth_cmpl->addr_type); + + // save remote versions to iot conf file + btm_status = BTM_ReadRemoteVersion(p_auth_cmpl->bd_addr, &lmp_ver, &mfct_set, + &lmp_subver); + + if (btm_status == BTM_SUCCESS) { + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, + IOT_CONF_KEY_MANUFACTURER, mfct_set); + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, IOT_CONF_KEY_LMPVER, + lmp_ver); + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_auth_cmpl->bd_addr, IOT_CONF_KEY_LMPSUBVER, + lmp_subver); + } + + // save remote pair type to iot conf file + btif_iot_save_pair_type(p_auth_cmpl->bd_addr, is_ble, is_ssp); + + device_iot_config_flush(); +} diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index 3217147e7d9..f74583db172 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -43,6 +43,7 @@ #include "bta/sys/bta_sys.h" #include "btif_config.h" #include "btif_profile_queue.h" +#include "device/include/device_iot_config.h" #include "internal_include/bt_target.h" #include "stack/include/gatt_api.h" #include "stack/include/l2c_api.h" @@ -209,13 +210,13 @@ static bool get_stack_is_running() { return stack_is_running; } extern const module_t bt_utils_module; extern const module_t bte_logmsg_module; extern const module_t btif_config_module; -extern const module_t bt_utils_module; extern const module_t gd_controller_module; extern const module_t gd_idle_module; extern const module_t gd_shim_module; extern const module_t interop_module; extern const module_t osi_module; extern const module_t stack_config_module; +extern const module_t device_iot_config_module; struct module_lookup { const char* name; @@ -232,6 +233,7 @@ const struct module_lookup module_table[] = { {INTEROP_MODULE, &interop_module}, {OSI_MODULE, &osi_module}, {STACK_CONFIG_MODULE, &stack_config_module}, + {DEVICE_IOT_CONFIG_MODULE, &device_iot_config_module}, {NULL, NULL}, }; @@ -254,6 +256,7 @@ static void init_stack_internal(bluetooth::core::CoreInterface* interface) { module_management_start(); + module_init(get_local_module(DEVICE_IOT_CONFIG_MODULE)); module_init(get_local_module(OSI_MODULE)); module_init(get_local_module(BT_UTILS_MODULE)); module_start_up(get_local_module(GD_IDLE_MODULE)); @@ -384,6 +387,7 @@ static void event_shut_down_stack(ProfileStopCallback stopProfiles) { BTA_dm_on_hw_off(); module_shut_down(get_local_module(BTIF_CONFIG_MODULE)); + module_shut_down(get_local_module(DEVICE_IOT_CONFIG_MODULE)); future_await(local_hack_future); @@ -434,6 +438,8 @@ static void event_clean_up_stack(std::promise<void> promise, module_clean_up(get_local_module(INTEROP_MODULE)); module_clean_up(get_local_module(BTIF_CONFIG_MODULE)); + module_clean_up(get_local_module(DEVICE_IOT_CONFIG_MODULE)); + module_clean_up(get_local_module(BT_UTILS_MODULE)); module_clean_up(get_local_module(OSI_MODULE)); module_shut_down(get_local_module(GD_IDLE_MODULE)); diff --git a/system/device/Android.bp b/system/device/Android.bp index 105dbe560d7..53383da41d7 100644 --- a/system/device/Android.bp +++ b/system/device/Android.bp @@ -25,6 +25,8 @@ cc_library_static { "src/controller.cc", "src/esco_parameters.cc", "src/interop.cc", + "src/device_iot_config.cc", + "src/device_iot_config_int.cc", ], min_sdk_version: "Tiramisu" } diff --git a/system/device/BUILD.gn b/system/device/BUILD.gn index b60059cbdcc..c57c8ee6027 100644 --- a/system/device/BUILD.gn +++ b/system/device/BUILD.gn @@ -19,6 +19,8 @@ static_library("device") { "src/controller.cc", "src/esco_parameters.cc", "src/interop.cc", + "src/device_iot_config.cc", + "src/device_iot_config_int.cc", ] include_dirs = [ diff --git a/system/device/include/device_iot_conf_defs.h b/system/device/include/device_iot_conf_defs.h new file mode 100644 index 00000000000..76f41248be1 --- /dev/null +++ b/system/device/include/device_iot_conf_defs.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#pragma once + +#define IOT_CONF_KEY_SECTION_ADAPTER "Adapter" +#define IOT_CONF_KEY_ADDRESS "Address" +#define IOT_CONF_KEY_BT_ONOFF_COUNT "BTOnOffCount" + +#define IOT_CONF_KEY_REMOTE_NAME "Name" +#define IOT_CONF_KEY_DEVCLASS "DevClass" +#define IOT_CONF_KEY_DEVTYPE "DevType" +#define IOT_CONF_KEY_ADDRTYPE "AddrType" +#define IOT_CONF_KEY_MANUFACTURER "Manufacturer" +#define IOT_CONF_KEY_LMPVER "LmpVer" +#define IOT_CONF_KEY_LMPSUBVER "LmpSubVer" +#define IOT_CONF_KEY_PAIRTYPE "PairType" +#define IOT_CONF_KEY_LE_PAIRTYPE "LE_PairType" +#define IOT_CONF_KEY_RT_SUPP_FEATURES "RemoteSupportedFeatures" +#define IOT_CONF_KEY_RT_EXT_FEATURES "RemoteExtendedFeatures" +#define IOT_CONF_KEY_LE_RT_FEATURES "LE_RemoteSupportedFeatures" +#define IOT_CONF_KEY_RECORDED "Recorded" + +#define IOT_CONF_KEY_GAP_CONN_COUNT "ProfileGap_ConnectCount" +#define IOT_CONF_KEY_GAP_CONN_FAIL_COUNT "ProfileGap_ConnectFailCount" +#define IOT_CONF_KEY_GAP_DISC_COUNT "ProfileGap_DiscCount" +#define IOT_CONF_KEY_GAP_DISC_AUTHFAIL_COUNT "ProfileGap_DiscAuthFailCount" +#define IOT_CONF_KEY_GAP_DISC_CONNTIMEOUT_COUNT \ + "ProfileGap_DiscConnTimeoutCount" +#define IOT_CONF_KEY_A2DP_ROLE "ProfileA2dp_Role" +#define IOT_CONF_KEY_A2DP_VERSION "ProfileA2dp_Version" +#define IOT_CONF_KEY_A2DP_CODECTYPE "ProfileA2dp_CodecType" +#define IOT_CONF_KEY_A2DP_CONN_COUNT "ProfileA2dp_ConnectCount" +#define IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT "ProfileA2dp_ConnectFailCount" +#define IOT_CONF_KEY_HFP_ROLE "ProfileHfp_Role" +#define IOT_CONF_KEY_HFP_VERSION "ProfileHfp_Version" +#define IOT_CONF_KEY_HFP_CODECTYPE "ProfileHfp_CodecType" +#define IOT_CONF_KEY_HFP_SLC_CONN_COUNT "ProfileHfp_SlcConnectCount" +#define IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT "ProfileHfp_SlcConnectFailCount" +#define IOT_CONF_KEY_HFP_SCO_CONN_COUNT "ProfileHfp_ScoConnectCount" +#define IOT_CONF_KEY_HFP_SCO_CONN_FAIL_COUNT "ProfileHfp_ScoConnectFailCount" +#define IOT_CONF_KEY_HFP_FEATURES "ProfileHfp_Features" +#define IOT_CONF_KEY_AVRCP_CTRL_VERSION "ProfileAvrcp_ControllerVersion" +#define IOT_CONF_KEY_AVRCP_TG_VERSION "ProfileAvrcp_TargetVersion" +#define IOT_CONF_KEY_AVRCP_CONN_COUNT "ProfileAvrcp_ConnectCount" +#define IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT "ProfileAvrcp_ConnectFailCount" +#define IOT_CONF_KEY_AVRCP_FEATURES "ProfileAvrcp_Features" +#define IOT_CONF_KEY_HID_ROLE "ProfileHid_Role" +#define IOT_CONF_KEY_HID_VERSION "ProfileHid_Version" +#define IOT_CONF_KEY_HID_CONN_COUNT "ProfileHid_ConnectCount" +#define IOT_CONF_KEY_HID_CONN_FAIL_COUNT "ProfileHid_ConnectFailCount" +#define IOT_CONF_KEY_PBAP_ROLE "ProfilePbap_Role" +#define IOT_CONF_KEY_PBAP_VERSION "ProfilePbap_Version" +#define IOT_CONF_KEY_PBAP_CONN_COUNT "ProfilePbap_ConnectCount" +#define IOT_CONF_KEY_PBAP_CONN_FAIL_COUNT "ProfilePbap_ConnectFailCount" +#define IOT_CONF_KEY_MAP_ROLE "ProfileMap_Role" +#define IOT_CONF_KEY_MAP_VERSION "ProfileMap_Version" +#define IOT_CONF_KEY_MAP_CONN_COUNT "ProfileMap_ConnectCount" +#define IOT_CONF_KEY_MAP_CONN_FAIL_COUNT "ProfileMap_ConnectFailCount" + +#define IOT_CONF_VAL_PAIR_TYPE_LEGACY 0 +#define IOT_CONF_VAL_PAIR_TYPE_SSP 1 +#define IOT_CONF_VAL_LE_PAIRTYPE_LEGACY 0 +#define IOT_CONF_VAL_LE_PAIRTYPE_SECURE 1 +#define IOT_CONF_VAL_RECORDED_DEFAULT 0 + +#define IOT_CONF_VAL_A2DP_ROLE_SINK 0 +#define IOT_CONF_VAL_A2DP_ROLE_SOURCE 1 +#define IOT_CONF_VAL_A2DP_CODECTYPE_SBC 0x01 +#define IOT_CONF_VAL_A2DP_CODECTYPE_APTX 0x02 +#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXHD 0x04 +#define IOT_CONF_VAL_A2DP_CODECTYPE_AAC 0x08 +#define IOT_CONF_VAL_A2DP_CODECTYPE_LDAC 0x10 +#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXADAPTIVE 0x20 +#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXTWS 0x40 + +#define IOT_CONF_VAL_HFP_ROLE_CLIENT 0 +#define IOT_CONF_VAL_HFP_ROLE_AG 1 +#define IOT_CONF_VAL_HFP_CODECTYPE_CVSD 0x01 +#define IOT_CONF_VAL_HFP_CODECTYPE_CVSDMSBC 0x02 + +#define IOT_CONF_VAL_HID_ROLE_HOST 0 +#define IOT_CONF_VAL_HID_ROLE_DEVICE 1 + +#define IOT_CONF_VAL_PBAP_ROLE_CLIENT 0 +#define IOT_CONF_VAL_PBAP_ROLE_SERVER 1 + +#define IOT_CONF_VAL_MAP_ROLE_CLIENT 0 +#define IOT_CONF_VAL_MAP_ROLE_SERVER 1 + +#define IOT_CONF_BYTE_NUM_1 1 +#define IOT_CONF_BYTE_NUM_2 2 +#define IOT_CONF_BYTE_NUM_3 3 +#define IOT_CONF_BYTE_NUM_4 4 \ No newline at end of file diff --git a/system/device/include/device_iot_config.h b/system/device/include/device_iot_config.h new file mode 100644 index 00000000000..df2f94c31a5 --- /dev/null +++ b/system/device/include/device_iot_config.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#pragma once + +#include <stdbool.h> +#include <stddef.h> + +#include "bt_target.h" +#include "bt_types.h" +#include "device_iot_conf_defs.h" +#include "raw_address.h" + +static const char DEVICE_IOT_CONFIG_MODULE[] = "device_iot_config_module"; + +bool device_iot_config_get_int(const std::string& section, + const std::string& key, int& value); +bool device_iot_config_set_int(const std::string& section, + const std::string& key, int value); +bool device_iot_config_int_add_one(const std::string& section, + const std::string& key); +bool device_iot_config_get_hex(const std::string& section, + const std::string& key, int& value); +bool device_iot_config_set_hex(const std::string& section, + const std::string& key, int value, int byte_num); +bool device_iot_config_set_hex_if_greater(const std::string& section, + const std::string& key, int value, + int byte_num); +bool device_iot_config_get_str(const std::string& section, + const std::string& key, char* value, + int* size_bytes); +bool device_iot_config_set_str(const std::string& section, + const std::string& key, + const std::string& value); +bool device_iot_config_get_bin(const std::string& section, + const std::string& key, uint8_t* value, + size_t* length); +bool device_iot_config_set_bin(const std::string& section, + const std::string& key, const uint8_t* value, + size_t length); +size_t device_iot_config_get_bin_length(const std::string& section, + const std::string& key); + +#define DEVICE_IOT_CONFIG_ADDR(method, addr, ...) \ + device_iot_config_##method((addr).ToString(), ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_GET_INT(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(get_int, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_SET_INT(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_int, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(int_add_one, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_GET_HEX(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(get_hex, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_SET_HEX(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_hex, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_hex_if_greater, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_GET_STR(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_gtr, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_SET_STR(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_str, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_GET_BIN(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(get_bin, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_SET_BIN(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(set_bin, addr, ##__VA_ARGS__) + +#define DEVICE_IOT_CONFIG_ADDR_GET_BIN_LENGTH(addr, ...) \ + DEVICE_IOT_CONFIG_ADDR(get_bin, addr, ##__VA_ARGS__) + +bool device_iot_config_has_section(const std::string& section); +bool device_iot_config_exist(const std::string& section, + const std::string& key); +bool device_iot_config_remove(const std::string& section, + const std::string& key); + +void device_iot_config_flush(void); +bool device_iot_config_clear(void); + +void device_debug_iot_config_dump(int fd); diff --git a/system/device/src/device_iot_config.cc b/system/device/src/device_iot_config.cc new file mode 100644 index 00000000000..8693d59bb51 --- /dev/null +++ b/system/device/src/device_iot_config.cc @@ -0,0 +1,379 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#include "bt_target.h" + +#define LOG_TAG "device_iot_config" +#include <base/logging.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <mutex> +#include <string> + +#include "bt_types.h" +#include "btcore/include/module.h" +#include "btif/include/btif_api.h" +#include "btif/include/btif_util.h" +#include "device/include/device_iot_config.h" +#include "device_iot_config_int.h" +#include "osi/include/alarm.h" +#include "osi/include/allocator.h" +#include "osi/include/compat.h" +#include "osi/include/config.h" +#include "osi/include/log.h" +#include "osi/include/osi.h" +#include "osi/include/properties.h" + +enum ConfigSource device_iot_config_source = NOT_LOADED; + +int device_iot_config_devices_loaded = -1; +char device_iot_config_time_created[TIME_STRING_LENGTH]; + +std::mutex config_lock; // protects operations on |config|. +std::unique_ptr<config_t> config; +alarm_t* config_timer; +bool iot_logging_enabled = false; + +bool device_iot_config_has_section(const std::string& section) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + return config_has_section(*config, section); +} + +bool device_iot_config_exist(const std::string& section, + const std::string& key) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + return config_has_key(*config, section, key); +} + +bool device_iot_config_get_int(const std::string& section, + const std::string& key, int& value) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + bool ret = config_has_key(*config, section, key); + if (ret) value = config_get_int(*config, section, key, value); + + return ret; +} + +bool device_iot_config_set_int(const std::string& section, + const std::string& key, int value) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + char value_str[32] = {0}; + snprintf(value_str, sizeof(value_str), "%d", value); + if (device_iot_config_has_key_value(section, key, value_str)) return true; + + config_set_string(config.get(), section, key, value_str); + device_iot_config_save_async(); + + return true; +} + +bool device_iot_config_int_add_one(const std::string& section, + const std::string& key) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + int result = 0; + std::unique_lock<std::mutex> lock(config_lock); + result = config_get_int(*config, section, key, result); + if (result >= 0) { + result += 1; + } else { + result = 0; + } + config_set_int(config.get(), section, key, result); + device_iot_config_save_async(); + + return true; +} + +bool device_iot_config_get_hex(const std::string& section, + const std::string& key, int& value) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + const std::string* stored_value = + config_get_string(*config, section, key, NULL); + if (!stored_value) return false; + + errno = 0; + char* endptr = nullptr; + int result = strtoul(stored_value->c_str(), &endptr, 16); + if (stored_value->c_str() == endptr) return false; + if (endptr == nullptr || endptr[0] != '\0') return false; + if (errno) return false; + + value = result; + return true; +} + +bool device_iot_config_set_hex(const std::string& section, + const std::string& key, int value, + int byte_num) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + char value_str[32] = {0}; + if (byte_num == 1) + snprintf(value_str, sizeof(value_str), "%02x", value); + else if (byte_num == 2) + snprintf(value_str, sizeof(value_str), "%04x", value); + else if (byte_num == 3) + snprintf(value_str, sizeof(value_str), "%06x", value); + else if (byte_num == 4) + snprintf(value_str, sizeof(value_str), "%08x", value); + + std::unique_lock<std::mutex> lock(config_lock); + if (device_iot_config_has_key_value(section, key, value_str)) return true; + + config_set_string(config.get(), section, key, value_str); + device_iot_config_save_async(); + + return true; +} + +bool device_iot_config_set_hex_if_greater(const std::string& section, + const std::string& key, int value, + int byte_num) { + CHECK_LOGGING_ENABLED(false); + + int stored_value = 0; + bool ret = device_iot_config_get_hex(section, key, stored_value); + if (ret && stored_value >= value) return true; + + return device_iot_config_set_hex(section, key, value, byte_num); +} + +bool device_iot_config_get_str(const std::string& section, + const std::string& key, char* value, + int* size_bytes) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + CHECK(value != NULL); + CHECK(size_bytes != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + const std::string* stored_value = + config_get_string(*config, section, key, NULL); + + if (!stored_value) return false; + + strlcpy(value, stored_value->c_str(), *size_bytes); + *size_bytes = strlen(value) + 1; + + return true; +} + +bool device_iot_config_set_str(const std::string& section, + const std::string& key, + const std::string& value) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + if (device_iot_config_has_key_value(section, key, value)) return true; + + config_set_string(config.get(), section, key, value); + device_iot_config_save_async(); + + return true; +} + +bool device_iot_config_get_bin(const std::string& section, + const std::string& key, uint8_t* value, + size_t* length) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + CHECK(value != NULL); + CHECK(length != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + const std::string* value_string = + config_get_string(*config, section, key, NULL); + + if (!value_string) return false; + + const char* value_str = value_string->c_str(); + + size_t value_len = strlen(value_str); + if ((value_len % 2) != 0 || *length < (value_len / 2)) return false; + + for (size_t i = 0; i < value_len; ++i) + if (!isxdigit(value_str[i])) return false; + + for (*length = 0; *value_str; value_str += 2, *length += 1) { + errno = 0; + char* endptr = nullptr; + value[*length] = strtoul(value_str, &endptr, 16); + if (value_str == endptr) return false; + if (*endptr) return false; + if (errno) return false; + } + + return true; +} + +size_t device_iot_config_get_bin_length(const std::string& section, + const std::string& key) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + const std::string* value_str = config_get_string(*config, section, key, NULL); + + if (!value_str) return 0; + + size_t value_len = strlen(value_str->c_str()); + return ((value_len % 2) != 0) ? 0 : (value_len / 2); +} + +bool device_iot_config_set_bin(const std::string& section, + const std::string& key, const uint8_t* value, + size_t length) { + CHECK_LOGGING_ENABLED(false); + + const char* lookup = "0123456789abcdef"; + + CHECK(config != NULL); + + LOG_VERBOSE("Key = %s", key.c_str()); + if (length > 0) CHECK(value != NULL); + + char* str = (char*)osi_calloc(length * 2 + 1); + if (str == NULL) { + LOG_ERROR("Unable to allocate a str."); + return false; + } + + for (size_t i = 0; i < length; ++i) { + str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F]; + str[(i * 2) + 1] = lookup[value[i] & 0x0F]; + } + + std::unique_lock<std::mutex> lock(config_lock); + if (device_iot_config_has_key_value(section, key, str)) { + osi_free(str); + return true; + } + + config_set_string(config.get(), section, key, str); + device_iot_config_save_async(); + + osi_free(str); + return true; +} + +bool device_iot_config_remove(const std::string& section, + const std::string& key) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + + std::unique_lock<std::mutex> lock(config_lock); + return config_remove_key(config.get(), section, key); +} + +void device_iot_config_flush(void) { + CHECK_LOGGING_ENABLED((void)0); + + CHECK(config != NULL); + CHECK(config_timer != NULL); + + int event = alarm_is_scheduled(config_timer) ? IOT_CONFIG_SAVE_TIMER_FIRED_EVT + : IOT_CONFIG_FLUSH_EVT; + LOG_VERBOSE("evt=%d", event); + alarm_cancel(config_timer); + device_iot_config_write(event, NULL); +} + +bool device_iot_config_clear(void) { + CHECK_LOGGING_ENABLED(false); + + CHECK(config != NULL); + CHECK(config_timer != NULL); + + LOG_INFO(""); + alarm_cancel(config_timer); + + std::unique_lock<std::mutex> lock(config_lock); + config.reset(); + + config = config_new_empty(); + if (config == NULL) { + return false; + } + + bool ret = config_save(*config, IOT_CONFIG_FILE_PATH); + device_iot_config_source = RESET; + return ret; +} + +void device_debug_iot_config_dump(int fd) { + CHECK_LOGGING_ENABLED((void)0); + + dprintf(fd, "\nBluetooth Iot Config:\n"); + + dprintf(fd, " Config Source: "); + switch (device_iot_config_source) { + case NOT_LOADED: + dprintf(fd, "Not loaded\n"); + break; + case ORIGINAL: + dprintf(fd, "Original file\n"); + break; + case BACKUP: + dprintf(fd, "Backup file\n"); + break; + case NEW_FILE: + dprintf(fd, "New file\n"); + break; + case RESET: + dprintf(fd, "Reset file\n"); + break; + } + + dprintf(fd, " Devices loaded: %d\n", device_iot_config_devices_loaded); + dprintf(fd, " File created/tagged: %s\n", device_iot_config_time_created); +} diff --git a/system/device/src/device_iot_config_int.cc b/system/device/src/device_iot_config_int.cc new file mode 100644 index 00000000000..e8f57b83f10 --- /dev/null +++ b/system/device/src/device_iot_config_int.cc @@ -0,0 +1,331 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#define LOG_TAG "device_iot_config" +#include "device_iot_config_int.h" + +#include <base/logging.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <mutex> +#include <string> + +#include "bt_types.h" +#include "btcore/include/module.h" +#include "btif/include/btif_api.h" +#include "btif/include/btif_util.h" +#include "common/init_flags.h" +#include "device/include/device_iot_config.h" +#include "osi/include/alarm.h" +#include "osi/include/allocator.h" +#include "osi/include/compat.h" +#include "osi/include/config.h" +#include "osi/include/log.h" +#include "osi/include/osi.h" +#include "osi/include/properties.h" + +extern enum ConfigSource device_iot_config_source; + +extern int device_iot_config_devices_loaded; +extern char device_iot_config_time_created[TIME_STRING_LENGTH]; + +extern std::mutex config_lock; // protects operations on |config|. +extern std::unique_ptr<config_t> config; +extern alarm_t* config_timer; +extern bool iot_logging_enabled; + +static void cleanup() { + alarm_free(config_timer); + config.reset(); + config_timer = NULL; + config = NULL; + device_iot_config_source = NOT_LOADED; +} + +// Module lifecycle functions +future_t* device_iot_config_module_init(void) { + LOG_INFO(""); + + std::unique_lock<std::mutex> lock(config_lock); + iot_logging_enabled = osi_property_get_bool(PROPERTY_ENABLE_LOGGING, false); + if (!iot_logging_enabled) { + device_iot_config_delete_files(); + return future_new_immediate(FUTURE_SUCCESS); + } + + if (device_iot_config_is_factory_reset()) { + device_iot_config_delete_files(); + } + + config = config_new(IOT_CONFIG_FILE_PATH); + device_iot_config_source = ORIGINAL; + if (!config) { + LOG_WARN("Unable to load config file: %s; using backup.", + IOT_CONFIG_FILE_PATH); + config = config_new(IOT_CONFIG_BACKUP_PATH); + device_iot_config_source = BACKUP; + } + + if (!config) { + LOG_ERROR("Unable to load bak file; creating empty config."); + config = config_new_empty(); + device_iot_config_source = NEW_FILE; + } + + if (!config) { + LOG_ERROR("Unable to allocate a config object."); + cleanup(); + return future_new_immediate(FUTURE_FAIL); + } + + int version; + if (device_iot_config_source == NEW_FILE) { + version = DEVICE_IOT_INFO_CURRENT_VERSION; + config_set_int(config.get(), INFO_SECTION, VERSION_KEY, version); + } else { + version = config_get_int(*config, INFO_SECTION, VERSION_KEY, -1); + if (version == -1) { + version = DEVICE_IOT_INFO_FIRST_VERSION; + config_set_int(config.get(), INFO_SECTION, VERSION_KEY, version); + } + } + + if (version != DEVICE_IOT_INFO_CURRENT_VERSION) { + LOG_INFO("Version in file is %d, CURRENT_VERSION is %d ", version, + DEVICE_IOT_INFO_CURRENT_VERSION); + remove(IOT_CONFIG_FILE_PATH); + remove(IOT_CONFIG_BACKUP_PATH); + config.reset(); + config = config_new_empty(); + if (!config) { + LOG_ERROR("Unable to allocate a config object."); + cleanup(); + return future_new_immediate(FUTURE_FAIL); + } + config_set_int(config.get(), INFO_SECTION, VERSION_KEY, + DEVICE_IOT_INFO_CURRENT_VERSION); + device_iot_config_source = NEW_FILE; + } + + device_iot_config_devices_loaded = device_iot_config_get_device_num(*config); + LOG_INFO("Devices loaded %d", device_iot_config_devices_loaded); + + // Read or set config file creation timestamp + const std::string* time_str = + config_get_string(*config, INFO_SECTION, FILE_CREATED_TIMESTAMP, NULL); + if (time_str != NULL) { + strncpy(device_iot_config_time_created, time_str->c_str(), + TIME_STRING_LENGTH); + } else { + // Read or set config file creation timestamp + time_t current_time = time(NULL); + struct tm* time_created = localtime(¤t_time); + if (time_created) { + strftime(device_iot_config_time_created, TIME_STRING_LENGTH, + TIME_STRING_FORMAT, time_created); + config_set_string(config.get(), INFO_SECTION, FILE_CREATED_TIMESTAMP, + std::string(device_iot_config_time_created)); + } + } + + // TODO: use a non-wake alarm for this once we have + // API support for it. There's no need to wake the system to + // write back to disk. + config_timer = alarm_new("btif.iot.config"); + if (!config_timer) { + LOG_ERROR("Unable to create alarm."); + cleanup(); + return future_new_immediate(FUTURE_FAIL); + } + + LOG_EVENT_INT(BT_IOT_CONFIG_SOURCE_TAG_NUM, device_iot_config_source); + + return future_new_immediate(FUTURE_SUCCESS); +} + +future_t* device_iot_config_module_start_up(void) { + LOG_INFO(""); + device_iot_config_int_add_one(IOT_CONF_KEY_SECTION_ADAPTER, + IOT_CONF_KEY_BT_ONOFF_COUNT); + return future_new_immediate(FUTURE_SUCCESS); +} + +future_t* device_iot_config_module_shut_down(void) { + LOG_INFO(""); + device_iot_config_flush(); + return future_new_immediate(FUTURE_SUCCESS); +} + +future_t* device_iot_config_module_clean_up(void) { + LOG_INFO(""); + if (config_timer != NULL && alarm_is_scheduled(config_timer)) + device_iot_config_flush(); + + alarm_free(config_timer); + config_timer = NULL; + + std::unique_lock<std::mutex> lock(config_lock); + config.reset(); + config = NULL; + return future_new_immediate(FUTURE_SUCCESS); +} + +EXPORT_SYMBOL module_t device_iot_config_module = { + .name = DEVICE_IOT_CONFIG_MODULE, + .init = device_iot_config_module_init, + .start_up = device_iot_config_module_start_up, + .shut_down = device_iot_config_module_shut_down, + .clean_up = device_iot_config_module_clean_up}; + +void device_iot_config_write(uint16_t event, UNUSED_ATTR char* p_param) { + CHECK_LOGGING_ENABLED((void)0); + + CHECK(config != NULL); + CHECK(config_timer != NULL); + + LOG_INFO("evt=%d", event); + std::unique_lock<std::mutex> lock(config_lock); + if (event == IOT_CONFIG_SAVE_TIMER_FIRED_EVT) { + device_iot_config_set_modified_time(); + } + + rename(IOT_CONFIG_FILE_PATH, IOT_CONFIG_BACKUP_PATH); + device_iot_config_restrict_device_num(*config); + device_iot_config_sections_sort_by_entry_key(*config, + device_iot_config_compare_key); + config_save(*config, IOT_CONFIG_FILE_PATH); +} + +void device_iot_config_sections_sort_by_entry_key(config_t& config, + compare_func comp) { + for (auto& entry : config.sections) { + entry.entries.sort(comp); + } +} + +bool device_iot_config_has_key_value(const std::string& section, + const std::string& key, + const std::string& value_str) { + CHECK(config != NULL); + + const std::string* stored_value = + config_get_string(*config, section, key, NULL); + + if (!stored_value || value_str.compare(*stored_value) != 0) return false; + + return true; +} + +void device_iot_config_save_async(void) { + CHECK(config != NULL); + CHECK(config_timer != NULL); + + LOG_VERBOSE(""); + alarm_set(config_timer, CONFIG_SETTLE_PERIOD_MS, + device_iot_config_timer_save_cb, NULL); +} + +int device_iot_config_get_device_num(const config_t& conf) { + CHECK_LOGGING_ENABLED(0); + + int devices = 0; + + for (const auto& entry : conf.sections) { + if (RawAddress::IsValidAddress(entry.name)) { + devices++; + } + } + return devices; +} + +void device_iot_config_restrict_device_num(config_t& config) { + int curr_num = device_iot_config_get_device_num(config); + int removed_devices = 0; + int need_remove_devices_num; + + if (curr_num <= DEVICES_MAX_NUM_IN_IOT_INFO_FILE) { + return; + } + + need_remove_devices_num = + curr_num - DEVICES_MAX_NUM_IN_IOT_INFO_FILE + DEVICES_NUM_MARGIN; + LOG_INFO("curr_num=%d, need_remove_num=%d", curr_num, + need_remove_devices_num); + + std::list<section_t>::iterator i = config.sections.begin(); + while (i != config.sections.end()) { + if (!RawAddress::IsValidAddress(i->name)) { + ++i; + continue; + } + + i = config.sections.erase(i); + if (++removed_devices >= need_remove_devices_num) { + break; + } + } +} + +bool device_iot_config_compare_key(const entry_t& first, + const entry_t& second) { + bool first_is_profile_key = strncasecmp(first.key.c_str(), "Profile", 7) == 0; + bool second_is_profile_key = + strncasecmp(second.key.c_str(), "Profile", 7) == 0; + if (!first_is_profile_key && !second_is_profile_key) { + return true; + } else if (first_is_profile_key && second_is_profile_key) { + return strcasecmp(first.key.c_str(), second.key.c_str()) <= 0; + } else { + return !first_is_profile_key; + } +} + +void device_iot_config_timer_save_cb(UNUSED_ATTR void* data) { + // Moving file I/O to btif context instead of timer callback because + // it usually takes a lot of time to be completed, introducing + // delays during A2DP playback causing blips or choppiness. + LOG_VERBOSE(""); + btif_transfer_context(device_iot_config_write, + IOT_CONFIG_SAVE_TIMER_FIRED_EVT, NULL, 0, NULL); +} + +void device_iot_config_set_modified_time() { + time_t current_time = time(NULL); + struct tm* time_modified = localtime(¤t_time); + char device_iot_config_time_modified[TIME_STRING_LENGTH]; + if (time_modified) { + strftime(device_iot_config_time_modified, TIME_STRING_LENGTH, + TIME_STRING_FORMAT, time_modified); + config_set_string(config.get(), INFO_SECTION, FILE_MODIFIED_TIMESTAMP, + device_iot_config_time_modified); + } +} + +bool device_iot_config_is_factory_reset(void) { + return osi_property_get_bool(PROPERTY_FACTORY_RESET, false); +} + +void device_iot_config_delete_files(void) { + remove(IOT_CONFIG_FILE_PATH); + remove(IOT_CONFIG_BACKUP_PATH); +} \ No newline at end of file diff --git a/system/device/src/device_iot_config_int.h b/system/device/src/device_iot_config_int.h new file mode 100644 index 00000000000..dc897703ed6 --- /dev/null +++ b/system/device/src/device_iot_config_int.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#pragma once + +#include "osi/include/config.h" +#include "osi/include/osi.h" + +#define BT_IOT_CONFIG_SOURCE_TAG_NUM 1010003 + +#define PROPERTY_ENABLE_LOGGING \ + "persist.bluetooth.device_iot_config.enablelogging" +#define PROPERTY_FACTORY_RESET "persist.bluetooth.factoryreset" + +#define INFO_SECTION "Info" +#define VERSION_KEY "Version" +#define FILE_CREATED_TIMESTAMP "TimeCreated" +#define FILE_MODIFIED_TIMESTAMP "TimeModified" +#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS") +static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S"; + +#ifndef DEVICES_MAX_NUM_IN_IOT_INFO_FILE +#define DEVICES_MAX_NUM_IN_IOT_INFO_FILE 40 +#endif +#define DEVICES_NUM_MARGIN 5 + +#if (DEVICES_MAX_NUM_IN_IOT_INFO_FILE < DEVICES_NUM_MARGIN) +#undef DEVICES_MAX_NUM_IN_IOT_INFO_FILE +#define DEVICES_MAX_NUM_IN_IOT_INFO_FILE DEVICES_NUM_MARGIN +#endif + +#define DEVICE_IOT_INFO_CURRENT_VERSION 1 +#define DEVICE_IOT_INFO_FIRST_VERSION 1 + +#define IOT_CONFIG_FLUSH_EVT 0 +#define IOT_CONFIG_SAVE_TIMER_FIRED_EVT 1 + +#if defined(OS_GENERIC) +static const char* IOT_CONFIG_FILE_PATH = "bt_remote_dev_info.conf"; +static const char* IOT_CONFIG_BACKUP_PATH = "bt_remote_dev_info.bak"; +#else // !defined(OS_GENERIC) +static const char* IOT_CONFIG_FILE_PATH = + "/data/misc/bluedroid/bt_remote_dev_info.conf"; +static const char* IOT_CONFIG_BACKUP_PATH = + "/data/misc/bluedroid/bt_remote_dev_info.bak"; +#endif // defined(OS_GENERIC) +static const uint64_t CONFIG_SETTLE_PERIOD_MS = 12000; + +enum ConfigSource { NOT_LOADED, ORIGINAL, BACKUP, NEW_FILE, RESET }; + +#define CHECK_LOGGING_ENABLED(return_value) \ + do { \ + if (!iot_logging_enabled) return (return_value); \ + } while (0) + +struct config_t; +struct future_t; + +typedef bool (*compare_func)(const entry_t& first, const entry_t& second); + +// config_lock is used by the callee in the following methods +future_t* device_iot_config_module_init(void); +future_t* device_iot_config_module_start_up(void); +future_t* device_iot_config_module_shut_down(void); +future_t* device_iot_config_module_clean_up(void); +void device_iot_config_write(uint16_t event, char* p_param); + +// config_lock is used by the caller of the following methods +void device_iot_config_sections_sort_by_entry_key(config_t& config, + compare_func comp); +bool device_iot_config_has_key_value(const std::string& section, + const std::string& key, + const std::string& value_str); +void device_iot_config_save_async(void); +int device_iot_config_get_device_num(const config_t& config); +void device_iot_config_restrict_device_num(config_t& config); +bool device_iot_config_compare_key(const entry_t& first, const entry_t& second); +void device_iot_config_timer_save_cb(UNUSED_ATTR void* data); +void device_iot_config_set_modified_time(); +bool device_iot_config_is_factory_reset(void); +void device_iot_config_delete_files(void); diff --git a/system/stack/Android.bp b/system/stack/Android.bp index ed8d3e4cedf..a2586142c10 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -65,6 +65,7 @@ cc_library_static { "packages/modules/Bluetooth/system/udrv/include", "packages/modules/Bluetooth/system/bta/include", "packages/modules/Bluetooth/system/bta/sys", + "packages/modules/Bluetooth/system/device/include", "packages/modules/Bluetooth/system/utils/include", "packages/modules/Bluetooth/system/gd/rust/shim", ], @@ -197,6 +198,7 @@ cc_library_static { "btm/btm_dev.cc", "btm/btm_devctl.cc", "btm/btm_inq.cc", + "btm/btm_iot_config.cc", "btm/btm_main.cc", "acl/btm_pm.cc", "btm/btm_sco.cc", @@ -884,6 +886,7 @@ cc_test { ], include_dirs: [ "packages/modules/Bluetooth/system", + "packages/modules/Bluetooth/system/device/include", "packages/modules/Bluetooth/system/gd", "packages/modules/Bluetooth/system/vnd/ble", ], @@ -933,6 +936,7 @@ cc_test { "btm/btm_dev.cc", "btm/btm_devctl.cc", "btm/btm_inq.cc", + "btm/btm_iot_config.cc", "btm/btm_iso.cc", "btm/btm_main.cc", "btm/btm_sco.cc", @@ -1329,11 +1333,13 @@ cc_test { ":TestMockStackSdp", ":TestMockStackSmp", "acl/*.cc", + "btm/btm_iot_config.cc", "test/stack_acl_test.cc", ], static_libs: [ "libbt-common", "libbt-protos-lite", + "libbtdevice", "libflatbuffers-cpp", "libgmock", "liblog", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index b9a47e8db95..f9a0e2ca84a 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -116,6 +116,7 @@ source_set("stack") { "btm/btm_dev.cc", "btm/btm_devctl.cc", "btm/btm_inq.cc", + "btm/btm_iot_config.cc", "btm/btm_iso.cc", "btm/btm_main.cc", "btm/btm_scn.cc", diff --git a/system/stack/a2dp/a2dp_codec_config.cc b/system/stack/a2dp/a2dp_codec_config.cc index 34503c8cfa6..6356d11aa49 100644 --- a/system/stack/a2dp/a2dp_codec_config.cc +++ b/system/stack/a2dp/a2dp_codec_config.cc @@ -37,6 +37,7 @@ #endif #include "bta/av/bta_av_int.h" +#include "device/include/device_iot_config.h" #include "osi/include/log.h" #include "osi/include/properties.h" #include "stack/include/bt_hdr.h" @@ -522,6 +523,44 @@ void A2dpCodecConfig::debug_codec_dump(int fd) { dprintf(fd, " Local capability: %s\n", result.c_str()); } +int A2DP_IotGetPeerSinkCodecType(const uint8_t* p_codec_info) { + int peer_codec_type = 0; + tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info); + LOG_VERBOSE("%s: codec_type = 0x%x", __func__, codec_type); + switch (codec_type) { + case A2DP_MEDIA_CT_SBC: + peer_codec_type = IOT_CONF_VAL_A2DP_CODECTYPE_SBC; + break; +#if !defined(EXCLUDE_NONSTANDARD_CODECS) + case A2DP_MEDIA_CT_NON_A2DP: { + uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); + uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); + + LOG_VERBOSE("%s codec_id = %d", __func__, codec_id); + LOG_VERBOSE("%s vendor_id = %x", __func__, vendor_id); + + if (codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH && + vendor_id == A2DP_APTX_VENDOR_ID) { + peer_codec_type = IOT_CONF_VAL_A2DP_CODECTYPE_APTX; + } else if (codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH && + vendor_id == A2DP_APTX_HD_VENDOR_ID) { + peer_codec_type = IOT_CONF_VAL_A2DP_CODECTYPE_APTXHD; + } else if (codec_id == A2DP_LDAC_CODEC_ID && + vendor_id == A2DP_LDAC_VENDOR_ID) { + peer_codec_type = IOT_CONF_VAL_A2DP_CODECTYPE_LDAC; + } + break; + } + case A2DP_MEDIA_CT_AAC: + peer_codec_type = IOT_CONF_VAL_A2DP_CODECTYPE_AAC; + break; +#endif + default: + break; + } + return peer_codec_type; +} + // // Compares two codecs |lhs| and |rhs| based on their priority. // Returns true if |lhs| has higher priority (larger priority value). diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 7eaa790566f..a35a931a836 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -42,6 +42,7 @@ #include "btif/include/btif_acl.h" #include "common/metrics.h" #include "device/include/controller.h" +#include "device/include/device_iot_config.h" #include "device/include/interop.h" #include "include/l2cap_hci_link_interface.h" #include "main/shim/acl_api.h" @@ -89,6 +90,8 @@ void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, void BTM_db_reset(void); extern tBTM_CB btm_cb; +extern void btm_iot_save_remote_properties(tACL_CONN* p_acl_cb); +extern void btm_iot_save_remote_versions(tACL_CONN* p_acl_cb); struct StackAclBtmAcl { tACL_CONN* acl_allocate_connection(); @@ -422,6 +425,10 @@ void btm_acl_created(const RawAddress& bda, uint16_t hci_handle, btm_ble_refresh_local_resolvable_private_addr( bda, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr); } + + // save remote properties to iot conf file + btm_iot_save_remote_properties(p_acl); + /* if BR/EDR do something more */ if (transport == BT_TRANSPORT_BR_EDR) { btsnd_hcic_read_rmt_clk_offset(hci_handle); @@ -817,6 +824,9 @@ static void maybe_chain_more_commands_after_read_remote_version_complete( bt_transport_text(p_acl_cb->transport).c_str(), PRIVATE_ADDRESS(p_acl_cb->remote_addr)); } + + // save remote versions to iot conf file + btm_iot_save_remote_versions(p_acl_cb); } void btm_process_remote_version_complete(uint8_t status, uint16_t handle, @@ -918,6 +928,13 @@ void btm_read_remote_features_complete(uint16_t handle, uint8_t* features) { HCI_FEATURE_BYTES_PER_PAGE); p_acl_cb->peer_lmp_feature_valid[0] = true; + /* save remote supported features to iot conf file */ + std::string key = IOT_CONF_KEY_RT_SUPP_FEATURES "_" + std::to_string(0); + + DEVICE_IOT_CONFIG_ADDR_SET_BIN(p_acl_cb->remote_addr, key, + p_acl_cb->peer_lmp_feature_pages[0], + BD_FEATURES_LEN); + if ((HCI_LMP_EXTENDED_SUPPORTED(p_acl_cb->peer_lmp_feature_pages[0])) && (controller_get_interface() ->supports_reading_remote_extended_features())) { @@ -993,6 +1010,13 @@ void btm_read_remote_ext_features_complete(uint16_t handle, uint8_t page_num, HCI_FEATURE_BYTES_PER_PAGE); p_acl_cb->peer_lmp_feature_valid[page_num] = true; + /* save remote extended features to iot conf file */ + std::string key = IOT_CONF_KEY_RT_EXT_FEATURES "_" + std::to_string(page_num); + + DEVICE_IOT_CONFIG_ADDR_SET_BIN(p_acl_cb->remote_addr, key, + p_acl_cb->peer_lmp_feature_pages[page_num], + BD_FEATURES_LEN); + /* If there is the next remote features page and * we have space to keep this page data - read this page */ if ((page_num < max_page) && (page_num < HCI_EXT_FEATURES_PAGE_MAX)) { @@ -2575,6 +2599,12 @@ bool acl_set_peer_le_features_from_handle(uint16_t hci_handle, STREAM_TO_ARRAY(p_acl->peer_le_features, p, BD_FEATURES_LEN); p_acl->peer_le_features_valid = true; LOG_DEBUG("Completed le feature read request"); + + /* save LE remote supported features to iot conf file */ + std::string key = IOT_CONF_KEY_RT_SUPP_FEATURES "_" + std::to_string(0); + + DEVICE_IOT_CONFIG_ADDR_SET_BIN(p_acl->remote_addr, key, + p_acl->peer_le_features, BD_FEATURES_LEN); return true; } diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index c4f82014f5c..9543f60393d 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -30,6 +30,7 @@ #include "avct_int.h" #include "bt_target.h" #include "bt_utils.h" +#include "device/include/device_iot_config.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "types/raw_address.h" @@ -173,6 +174,10 @@ void avct_lcb_event(tAVCT_LCB* p_lcb, uint8_t event, tAVCT_LCB_EVT* p_data) { /* look up the state table for the current state */ state_table = avct_lcb_st_tbl[p_lcb->state]; + if (p_lcb->state == AVCT_LCB_IDLE_ST && event == AVCT_LCB_LL_OPEN_EVT) + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_lcb->peer_addr, + IOT_CONF_KEY_AVRCP_CONN_COUNT); + /* set next state */ p_lcb->state = state_table[event][AVCT_LCB_NEXT_STATE]; diff --git a/system/stack/avct/avct_lcb_act.cc b/system/stack/avct/avct_lcb_act.cc index 2a2f6b2161b..67431f1e20b 100644 --- a/system/stack/avct/avct_lcb_act.cc +++ b/system/stack/avct/avct_lcb_act.cc @@ -30,6 +30,7 @@ #include "bt_utils.h" #include "bta/include/bta_api.h" #include "btm_api.h" +#include "device/include/device_iot_config.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "osi/include/osi.h" @@ -251,6 +252,8 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { /* if no ccbs bound to this lcb, disconnect */ if (!bind) { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_lcb->peer_addr, + IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT); avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data); } } @@ -274,6 +277,8 @@ void avct_lcb_open_fail(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT, p_data->result, &p_lcb->peer_addr); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_lcb->peer_addr, + IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT); } } } @@ -410,6 +415,8 @@ void avct_lcb_chnl_disc(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { ******************************************************************************/ void avct_lcb_bind_fail(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_lcb->peer_addr, + IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT); } /******************************************************************************* diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc index 276dd14c766..25e19819f42 100644 --- a/system/stack/btm/btm_ble.cc +++ b/system/stack/btm/btm_ble.cc @@ -25,8 +25,11 @@ #define LOG_TAG "bt_btm_ble" +#include <base/logging.h> + #include <cstdint> +#include "btif/include/btif_storage.h" #include "device/include/controller.h" #include "main/shim/btm_api.h" #include "main/shim/l2c_api.h" @@ -48,8 +51,6 @@ #include "stack/include/smp_api.h" #include "types/raw_address.h" -#include <base/logging.h> - extern tBTM_CB btm_cb; extern bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec, @@ -111,6 +112,33 @@ void BTM_SecAddBleDevice(const RawAddress& bd_addr, tBT_DEVICE_TYPE dev_type, } } +/******************************************************************************* + * + * Function BTM_GetRemoteDeviceName + * + * Description This function is called to get the dev name of remote device + * from NV + * + * Returns TRUE if success; otherwise failed. + * + ******************************************************************************/ +bool BTM_GetRemoteDeviceName(const RawAddress& bd_addr, BD_NAME bd_name) { + BTM_TRACE_DEBUG("%s", __func__); + bool ret = FALSE; + bt_bdname_t bdname; + bt_property_t prop_name; + BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME, + sizeof(bt_bdname_t), &bdname); + + if (btif_storage_get_remote_device_property(&bd_addr, &prop_name) == + BT_STATUS_SUCCESS) { + APPL_TRACE_DEBUG("%s, NV name = %s", __func__, bdname.name); + strncpy((char*)bd_name, (char*)bdname.name, BD_NAME_LEN + 1); + ret = TRUE; + } + return ret; +} + /******************************************************************************* * * Function BTM_SecAddBleKey diff --git a/system/stack/btm/btm_iot_config.cc b/system/stack/btm/btm_iot_config.cc new file mode 100644 index 00000000000..be80f43a233 --- /dev/null +++ b/system/stack/btm/btm_iot_config.cc @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * Copyright (C) 2018 The Linux Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include "bt_target.h" +#include "btif/include/btif_storage.h" +#include "btif/include/btif_util.h" +#include "btm_ble_api.h" +#include "btm_int_types.h" +#include "device/include/device_iot_config.h" + +/******************************************************************************* + * + * Function btm_iot_save_remote_properties + * + * Description Store remote basic properties to iot conf file + * + * Returns void + * + *******************************************************************************/ +void btm_iot_save_remote_properties(tACL_CONN* p_acl_cb) { + BD_NAME bd_name; + bt_property_t prop_name; + uint32_t cod = 0; + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; + + // save remote name to iot conf file + if (BTM_GetRemoteDeviceName(p_acl_cb->remote_addr, bd_name)) { + std::string name_str{(char*)bd_name}; + DEVICE_IOT_CONFIG_ADDR_SET_STR(p_acl_cb->remote_addr, + IOT_CONF_KEY_REMOTE_NAME, name_str); + } + + /* Try to retrieve cod from storage */ + BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_CLASS_OF_DEVICE, + sizeof(cod), &cod); + if (btif_storage_get_remote_device_property(&p_acl_cb->remote_addr, + &prop_name) == BT_STATUS_SUCCESS) + BTIF_TRACE_DEBUG("%s cod retrieved from storage is 0x%06x", __func__, cod); + if (cod == 0) { + BTIF_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__); + cod = (0x1F) << 8; + } + + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_DEVCLASS, + (int)cod); + + BTM_ReadDevInfo(p_acl_cb->remote_addr, &dev_type, &addr_type); + + // save remote dev type to iot conf file + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_DEVTYPE, + (int)dev_type); + + // save remote addr type to iot conf file + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_ADDRTYPE, + (int)addr_type); + + // save default recorded value to iot conf file + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_RECORDED, + IOT_CONF_VAL_RECORDED_DEFAULT); +} + +/******************************************************************************* + * + * Function btm_iot_save_remote_versions + * + * Description Store remote versions to iot conf file + * + * Returns void + * + *******************************************************************************/ +void btm_iot_save_remote_versions(tACL_CONN* p_acl_cb) { + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, + IOT_CONF_KEY_MANUFACTURER, + p_acl_cb->remote_version_info.manufacturer); + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_LMPVER, + p_acl_cb->remote_version_info.lmp_version); + DEVICE_IOT_CONFIG_ADDR_SET_INT(p_acl_cb->remote_addr, IOT_CONF_KEY_LMPSUBVER, + p_acl_cb->remote_version_info.lmp_subversion); +} diff --git a/system/stack/btm/btm_sco.cc b/system/stack/btm/btm_sco.cc index d31ff62a84f..7d9773bc1af 100644 --- a/system/stack/btm/btm_sco.cc +++ b/system/stack/btm/btm_sco.cc @@ -31,6 +31,7 @@ #include <string> #include "device/include/controller.h" +#include "device/include/device_iot_config.h" #include "embdrv/sbc/decoder/include/oi_codec_sbc.h" #include "embdrv/sbc/decoder/include/oi_status.h" #include "osi/include/allocator.h" @@ -807,6 +808,8 @@ void btm_sco_conn_req(const RawAddress& bda, const DEV_CLASS& dev_class, tSCO_CONN* p = &p_sco->sco_db[0]; tBTM_ESCO_CONN_REQ_EVT_DATA evt_data = {}; + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(bda, IOT_CONF_KEY_HFP_SCO_CONN_COUNT); + for (uint16_t sco_index = 0; sco_index < BTM_MAX_SCO_LINKS; sco_index++, p++) { /* @@ -987,8 +990,12 @@ void btm_sco_connection_failed(tHCI_STATUS hci_status, const RawAddress& bda, if (p->state == SCO_ST_CONNECTING) { p->state = SCO_ST_UNUSED; (*p->p_disc_cb)(xx); - } else + } else { p->state = SCO_ST_LISTENING; + if (bda != RawAddress::kEmpty) + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE( + bda, IOT_CONF_KEY_HFP_SCO_CONN_FAIL_COUNT); + } BTM_LogHistory( kBtmLogTag, bda, "Connection failed", base::StringPrintf( diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index 0668c33ba96..1394d95204b 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -36,6 +36,7 @@ #include "common/metrics.h" #include "common/time_util.h" #include "device/include/controller.h" +#include "device/include/device_iot_config.h" #include "l2c_api.h" #include "main/shim/btm_api.h" #include "main/shim/dumpsys.h" @@ -3788,7 +3789,11 @@ void btm_sec_disconnected(uint16_t handle, tHCI_REASON reason, status = HCI_ERR_REPEATED_ATTEMPTS; } else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) { status = HCI_ERR_HOST_REJECT_SECURITY; + } else { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(p_dev_rec->bd_addr, + IOT_CONF_KEY_GAP_DISC_AUTHFAIL_COUNT); } + NotifyBondingChange(*p_dev_rec, status); p_dev_rec = btm_find_dev_by_handle(handle); diff --git a/system/stack/hcic/hcicmds.cc b/system/stack/hcic/hcicmds.cc index 1fea1cd463c..d41f11c2f8f 100644 --- a/system/stack/hcic/hcicmds.cc +++ b/system/stack/hcic/hcicmds.cc @@ -29,6 +29,7 @@ #include "bt_target.h" #include "btu.h" +#include "device/include/device_iot_config.h" #include "device/include/esco_parameters.h" #include "hcidefs.h" #include "hcimsgs.h" @@ -567,6 +568,7 @@ void btsnd_hcic_create_conn(const RawAddress& dest, uint16_t packet_types, acl_cache_role(dest, HCI_ROLE_CENTRAL, /*overwrite_cache=*/false); btm_acl_paging(p, dest); + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(dest, IOT_CONF_KEY_GAP_CONN_COUNT); } static void btsnd_hcic_disconnect(uint16_t handle, uint8_t reason) { diff --git a/system/stack/include/a2dp_codec_api.h b/system/stack/include/a2dp_codec_api.h index 2d0e7d2ba20..01e01fd5159 100644 --- a/system/stack/include/a2dp_codec_api.h +++ b/system/stack/include/a2dp_codec_api.h @@ -587,6 +587,10 @@ bool A2DP_IsPeerSinkCodecValid(const uint8_t* p_codec_info); // Returns true if the A2DP Sink codec is supported, otherwise false. bool A2DP_IsSinkCodecSupported(const uint8_t* p_codec_info); +// Gets peer sink endpoint codec type. +// |p_codec_info| contains information about the codec capabilities. +int A2DP_IotGetPeerSinkCodecType(const uint8_t* p_codec_info); + // Checks whether an A2DP Source codec for a peer Source device is supported. // |p_codec_info| contains information about the codec capabilities of the // peer device. diff --git a/system/stack/include/btm_ble_api.h b/system/stack/include/btm_ble_api.h index e980906cef5..fb74fe8aeb1 100644 --- a/system/stack/include/btm_ble_api.h +++ b/system/stack/include/btm_ble_api.h @@ -460,6 +460,18 @@ extern void BTM_ReadDevInfo(const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type, tBLE_ADDR_TYPE* p_addr_type); +/******************************************************************************* + * + * Function BTM_GetRemoteDeviceName + * + * Description This function is called to get the dev name of remote device + * from NV + * + * Returns true if success; otherwise failed. + * + *******************************************************************************/ +extern bool BTM_GetRemoteDeviceName(const RawAddress& bda, BD_NAME bd_name); + /******************************************************************************* * * Function BTM_ReadConnectedTransportAddress diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc index f2be73891ec..1d31102f649 100644 --- a/system/stack/l2cap/l2c_link.cc +++ b/system/stack/l2cap/l2c_link.cc @@ -27,6 +27,7 @@ #include <cstdint> +#include "device/include/device_iot_config.h" #include "main/shim/l2c_api.h" #include "main/shim/shim.h" #include "osi/include/allocator.h" @@ -325,6 +326,36 @@ void l2c_link_sec_comp2(const RawAddress& p_bda, } } +/******************************************************************************* +** +** Function l2c_link_iot_store_disc_reason +** +** Description iot store disconnection reason to local conf file +** +** Returns void +** +*******************************************************************************/ +static void l2c_link_iot_store_disc_reason(RawAddress& bda, uint8_t reason) { + const char* disc_keys[] = { + IOT_CONF_KEY_GAP_DISC_CONNTIMEOUT_COUNT, + }; + const uint8_t disc_reasons[] = { + HCI_ERR_CONNECTION_TOUT, + }; + int i = 0; + int num = sizeof(disc_keys) / sizeof(disc_keys[0]); + + if (reason == (uint8_t)-1) return; + + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(bda, IOT_CONF_KEY_GAP_DISC_COUNT); + for (i = 0; i < num; i++) { + if (disc_reasons[i] == reason) { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(bda, disc_keys[i]); + break; + } + } +} + /******************************************************************************* * * Function l2c_link_hci_disc_comp @@ -349,6 +380,8 @@ bool l2c_link_hci_disc_comp(uint16_t handle, tHCI_REASON reason) { if (!p_lcb) { status = false; } else { + l2c_link_iot_store_disc_reason(p_lcb->remote_bd_addr, reason); + p_lcb->SetDisconnectReason(reason); /* Just in case app decides to try again in the callback context */ diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc index e2824588fa1..9964c1d8c4d 100644 --- a/system/stack/test/btm/stack_btm_test.cc +++ b/system/stack/test/btm/stack_btm_test.cc @@ -54,6 +54,7 @@ namespace mock = test::mock::stack_hcic_hcicmds; extern tBTM_CB btm_cb; +uint8_t btif_trace_level = BT_TRACE_LEVEL_DEBUG; uint8_t appl_trace_level = BT_TRACE_LEVEL_VERBOSE; btif_hh_cb_t btif_hh_cb; tL2C_CB l2cb; diff --git a/system/stack/test/stack_acl_test.cc b/system/stack/test/stack_acl_test.cc index 6b741e2d19a..c479a1e28e7 100644 --- a/system/stack/test/stack_acl_test.cc +++ b/system/stack/test/stack_acl_test.cc @@ -33,6 +33,7 @@ #include "types/hci_role.h" #include "types/raw_address.h" +uint8_t btif_trace_level = BT_TRACE_LEVEL_DEBUG; tBTM_CB btm_cb; void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {} diff --git a/system/test/mock/mock_stack_a2dp_codec_config.cc b/system/test/mock/mock_stack_a2dp_codec_config.cc index 066f82fa4af..81ecb077684 100644 --- a/system/test/mock/mock_stack_a2dp_codec_config.cc +++ b/system/test/mock/mock_stack_a2dp_codec_config.cc @@ -345,6 +345,10 @@ void A2DP_InitDefaultCodec(uint8_t* p_codec_info) { void A2dpCodecConfig::debug_codec_dump(int fd) { mock_function_count_map[__func__]++; } +int A2DP_IotGetPeerSinkCodecType(const uint8_t* p_codec_info) { + mock_function_count_map[__func__]++; + return 0; +} void A2dpCodecConfig::setCodecPriority( btav_a2dp_codec_priority_t codec_priority) { mock_function_count_map[__func__]++; diff --git a/system/test/mock/mock_stack_btm_ble.cc b/system/test/mock/mock_stack_btm_ble.cc index 8d1871671eb..99843587160 100644 --- a/system/test/mock/mock_stack_btm_ble.cc +++ b/system/test/mock/mock_stack_btm_ble.cc @@ -57,6 +57,7 @@ struct BTM_GetDeviceEncRoot BTM_GetDeviceEncRoot; struct BTM_GetDeviceIDRoot BTM_GetDeviceIDRoot; struct BTM_ReadConnectedTransportAddress BTM_ReadConnectedTransportAddress; struct BTM_ReadDevInfo BTM_ReadDevInfo; +struct BTM_GetRemoteDeviceName BTM_GetRemoteDeviceName; struct BTM_SecAddBleDevice BTM_SecAddBleDevice; struct BTM_SecAddBleKey BTM_SecAddBleKey; struct BTM_SecurityGrant BTM_SecurityGrant; @@ -103,6 +104,7 @@ namespace test { namespace mock { namespace stack_btm_ble { +bool BTM_GetRemoteDeviceName::return_value = false; bool BTM_BleDataSignature::return_value = false; bool BTM_BleVerifySignature::return_value = false; const Octet16 BTM_GetDeviceDHK::return_value{0xd5, 0xcb, 0x84, 0x54, 0xd1, 0x77, @@ -231,6 +233,10 @@ void BTM_ReadDevInfo(const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type, test::mock::stack_btm_ble::BTM_ReadDevInfo(remote_bda, p_dev_type, p_addr_type); } +bool BTM_GetRemoteDeviceName(const RawAddress& bd_addr, BD_NAME bd_name) { + mock_function_count_map[__func__]++; + return test::mock::stack_btm_ble::BTM_GetRemoteDeviceName(bd_addr, bd_name); +} void BTM_SecAddBleDevice(const RawAddress& bd_addr, tBT_DEVICE_TYPE dev_type, tBLE_ADDR_TYPE addr_type) { mock_function_count_map[__func__]++; diff --git a/system/test/mock/mock_stack_btm_ble.h b/system/test/mock/mock_stack_btm_ble.h index 3881d68f6f2..e68edb7213d 100644 --- a/system/test/mock/mock_stack_btm_ble.h +++ b/system/test/mock/mock_stack_btm_ble.h @@ -334,6 +334,19 @@ struct BTM_SecAddBleDevice { }; extern struct BTM_SecAddBleDevice BTM_SecAddBleDevice; +// Name: BTM_GetRemoteDeviceName +// Params: const RawAddress& bd_addr, BD_NAME bd_name +// Return: bool +struct BTM_GetRemoteDeviceName { + static bool return_value; + std::function<bool(const RawAddress& bd_addr, BD_NAME bd_name)> body{ + [](const RawAddress& bd_addr, BD_NAME bd_name) { return return_value; }}; + bool operator()(const RawAddress& bd_addr, BD_NAME bd_name) { + return body(bd_addr, bd_name); + }; +}; +extern struct BTM_GetRemoteDeviceName BTM_GetRemoteDeviceName; + // Name: BTM_SecAddBleKey // Params: const RawAddress& bd_addr, tBTM_LE_KEY_VALUE* p_le_key, // tBTM_LE_KEY_TYPE key_type Return: void -- GitLab