Loading system/btif/src/stack_manager.cc +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include "internal_include/stack_config.h" #include "rust/src/core/ffi/module.h" #include "stack/btm/btm_ble_int.h" #include "stack/include/ais_api.h" #include "stack/include/smp_api.h" #ifndef BT_STACK_CLEANUP_WAIT_MS Loading Loading @@ -301,6 +302,7 @@ static void event_start_up_stack(bluetooth::core::CoreInterface* interface, RFCOMM_Init(); GAP_Init(); AIS_Init(); startProfiles(); Loading system/stack/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ cc_library_static { name: "libbt-stack", defaults: ["fluoride_defaults"], local_include_dirs: [ "ais", "avct", "avdt", "avrc", Loading Loading @@ -180,6 +181,7 @@ cc_library_static { name: "libbt-stack-core", defaults: ["fluoride_defaults"], local_include_dirs: [ "ais", "avct", "avdt", "avrc", Loading Loading @@ -213,6 +215,7 @@ cc_library_static { "acl/ble_acl.cc", "acl/btm_acl.cc", "acl/btm_pm.cc", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", "btm/ble_scanner_hci_interface.cc", "btm/btm_ble.cc", Loading Loading @@ -517,6 +520,7 @@ cc_fuzz { ":TestMockStackL2cap", ":TestMockStackMetrics", ":TestMockStackSdp", "ais/*.cc", "eatt/*.cc", "fuzzers/gatt_fuzzer.cc", "gatt/*.cc", Loading Loading @@ -1973,6 +1977,7 @@ cc_test { ":TestMockStackL2cap", ":TestMockStackSdp", ":TestMockStackSmp", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", "eatt/eatt.cc", "gatt/att_protocol.cc", Loading system/stack/BUILD.gn +2 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ source_set("nonstandard_codecs") { source_set("stack") { sources = [ "ais/ais_ble.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_ext.cc", Loading Loading @@ -187,6 +188,7 @@ source_set("stack") { include_dirs = [ ".", "include", "ais", "avct", "btm", "avrc", Loading system/stack/ais/ais_ble.cc 0 → 100644 +144 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright 2024 The Android Open Source Project * * 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 <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <string.h> #include <array> #include "os/system_properties.h" #include "stack/include/ais_api.h" #include "stack/include/bt_types.h" #include "stack/include/gatt_api.h" #include "types/bluetooth/uuid.h" using bluetooth::Uuid; using bluetooth::log::error; using bluetooth::log::warn; static const char kPropertyAndroidAPILevel[] = "ro.build.version.sdk"; static const uint32_t kPropertyAndroidAPILevelDefault = 0; const Uuid ANDROID_INFORMATION_SERVICE_UUID = Uuid::FromString(ANDROID_INFORMATION_SERVICE_UUID_STRING); const Uuid GATT_UUID_AIS_API_LEVEL = Uuid::FromString(GATT_UUID_AIS_API_LEVEL_STRING); /* LE AIS attribute handle */ static uint16_t attr_api_level_handle; static uint32_t api_level; void ais_request_cback(uint16_t, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*); static tGATT_CBACK ais_cback = { .p_conn_cb = nullptr, .p_cmpl_cb = nullptr, .p_disc_res_cb = nullptr, .p_disc_cmpl_cb = nullptr, .p_req_cb = ais_request_cback, .p_enc_cmpl_cb = nullptr, .p_congestion_cb = nullptr, .p_phy_update_cb = nullptr, .p_conn_update_cb = nullptr, .p_subrate_chg_cb = nullptr, }; /** AIS ATT server attribute access request callback */ void ais_request_cback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) { tGATT_STATUS status = GATT_INVALID_PDU; tGATTS_RSP rsp_msg = {}; uint16_t handle = p_data->read_req.handle; tGATT_VALUE* p_value = &rsp_msg.attr_value; uint8_t* p = p_value->value; if (type == GATTS_REQ_TYPE_READ_CHARACTERISTIC) { p_value->handle = handle; if (handle == attr_api_level_handle) { if (p_data->read_req.is_long) { p_value->offset = p_data->read_req.offset; status = GATT_NOT_LONG; } else { UINT32_TO_STREAM(p, api_level); p_value->len = 4; status = GATT_SUCCESS; } } else { status = GATT_NOT_FOUND; } } else { warn("Unknown/unexpected LE AIS ATT request: 0x{:02x}", type); } if (GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg) != GATT_SUCCESS) { warn("Unable to send GATT server response conn_id:{}", conn_id); } } /******************************************************************************* * * Function ais_attr_db_init * * Description AIS ATT database initialization. * * Returns void. * ******************************************************************************/ void ais_attr_db_init(void) { if (!com::android::bluetooth::flags::android_os_identifier()) { return; } api_level = bluetooth::os::GetSystemPropertyUint32(kPropertyAndroidAPILevel, kPropertyAndroidAPILevelDefault); // Add Android OS identifier if API level is defined. if (api_level != kPropertyAndroidAPILevelDefault) { std::array<uint8_t, Uuid::kNumBytes128> tmp; tmp.fill(0xc5); // any number is fine here Uuid app_uuid = Uuid::From128BitBE(tmp); tGATT_IF gatt_if = GATT_Register(app_uuid, "Ais", &ais_cback, false); GATT_StartIf(gatt_if); btgatt_db_element_t android_information_service[] = { { .uuid = ANDROID_INFORMATION_SERVICE_UUID, .type = BTGATT_DB_PRIMARY_SERVICE, }, { .uuid = GATT_UUID_AIS_API_LEVEL, .type = BTGATT_DB_CHARACTERISTIC, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ_IF_ENCRYPTED_OR_DISCOVERABLE, }}; if (GATTS_AddService(gatt_if, android_information_service, sizeof(android_information_service) / sizeof(btgatt_db_element_t)) != GATT_SERVICE_STARTED) { error("Unable to add Android Information Server gatt_if:{}", gatt_if); } attr_api_level_handle = android_information_service[1].attribute_handle; } } /* * This routine should not be called except once per stack invocation. */ void AIS_Init(void) { ais_attr_db_init(); } system/stack/fuzzers/gatt_fuzzer.cc +3 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,9 @@ namespace os { bool GetSystemPropertyBool(const std::string& property, bool default_value) { return default_value; } uint32_t GetSystemPropertyUint32(const std::string& property, uint32_t default_value) { return default_value; } } // namespace os } // namespace bluetooth Loading Loading
system/btif/src/stack_manager.cc +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include "internal_include/stack_config.h" #include "rust/src/core/ffi/module.h" #include "stack/btm/btm_ble_int.h" #include "stack/include/ais_api.h" #include "stack/include/smp_api.h" #ifndef BT_STACK_CLEANUP_WAIT_MS Loading Loading @@ -301,6 +302,7 @@ static void event_start_up_stack(bluetooth::core::CoreInterface* interface, RFCOMM_Init(); GAP_Init(); AIS_Init(); startProfiles(); Loading
system/stack/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ cc_library_static { name: "libbt-stack", defaults: ["fluoride_defaults"], local_include_dirs: [ "ais", "avct", "avdt", "avrc", Loading Loading @@ -180,6 +181,7 @@ cc_library_static { name: "libbt-stack-core", defaults: ["fluoride_defaults"], local_include_dirs: [ "ais", "avct", "avdt", "avrc", Loading Loading @@ -213,6 +215,7 @@ cc_library_static { "acl/ble_acl.cc", "acl/btm_acl.cc", "acl/btm_pm.cc", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", "btm/ble_scanner_hci_interface.cc", "btm/btm_ble.cc", Loading Loading @@ -517,6 +520,7 @@ cc_fuzz { ":TestMockStackL2cap", ":TestMockStackMetrics", ":TestMockStackSdp", "ais/*.cc", "eatt/*.cc", "fuzzers/gatt_fuzzer.cc", "gatt/*.cc", Loading Loading @@ -1973,6 +1977,7 @@ cc_test { ":TestMockStackL2cap", ":TestMockStackSdp", ":TestMockStackSmp", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", "eatt/eatt.cc", "gatt/att_protocol.cc", Loading
system/stack/BUILD.gn +2 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ source_set("nonstandard_codecs") { source_set("stack") { sources = [ "ais/ais_ble.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_ext.cc", Loading Loading @@ -187,6 +188,7 @@ source_set("stack") { include_dirs = [ ".", "include", "ais", "avct", "btm", "avrc", Loading
system/stack/ais/ais_ble.cc 0 → 100644 +144 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright 2024 The Android Open Source Project * * 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 <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <string.h> #include <array> #include "os/system_properties.h" #include "stack/include/ais_api.h" #include "stack/include/bt_types.h" #include "stack/include/gatt_api.h" #include "types/bluetooth/uuid.h" using bluetooth::Uuid; using bluetooth::log::error; using bluetooth::log::warn; static const char kPropertyAndroidAPILevel[] = "ro.build.version.sdk"; static const uint32_t kPropertyAndroidAPILevelDefault = 0; const Uuid ANDROID_INFORMATION_SERVICE_UUID = Uuid::FromString(ANDROID_INFORMATION_SERVICE_UUID_STRING); const Uuid GATT_UUID_AIS_API_LEVEL = Uuid::FromString(GATT_UUID_AIS_API_LEVEL_STRING); /* LE AIS attribute handle */ static uint16_t attr_api_level_handle; static uint32_t api_level; void ais_request_cback(uint16_t, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*); static tGATT_CBACK ais_cback = { .p_conn_cb = nullptr, .p_cmpl_cb = nullptr, .p_disc_res_cb = nullptr, .p_disc_cmpl_cb = nullptr, .p_req_cb = ais_request_cback, .p_enc_cmpl_cb = nullptr, .p_congestion_cb = nullptr, .p_phy_update_cb = nullptr, .p_conn_update_cb = nullptr, .p_subrate_chg_cb = nullptr, }; /** AIS ATT server attribute access request callback */ void ais_request_cback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) { tGATT_STATUS status = GATT_INVALID_PDU; tGATTS_RSP rsp_msg = {}; uint16_t handle = p_data->read_req.handle; tGATT_VALUE* p_value = &rsp_msg.attr_value; uint8_t* p = p_value->value; if (type == GATTS_REQ_TYPE_READ_CHARACTERISTIC) { p_value->handle = handle; if (handle == attr_api_level_handle) { if (p_data->read_req.is_long) { p_value->offset = p_data->read_req.offset; status = GATT_NOT_LONG; } else { UINT32_TO_STREAM(p, api_level); p_value->len = 4; status = GATT_SUCCESS; } } else { status = GATT_NOT_FOUND; } } else { warn("Unknown/unexpected LE AIS ATT request: 0x{:02x}", type); } if (GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg) != GATT_SUCCESS) { warn("Unable to send GATT server response conn_id:{}", conn_id); } } /******************************************************************************* * * Function ais_attr_db_init * * Description AIS ATT database initialization. * * Returns void. * ******************************************************************************/ void ais_attr_db_init(void) { if (!com::android::bluetooth::flags::android_os_identifier()) { return; } api_level = bluetooth::os::GetSystemPropertyUint32(kPropertyAndroidAPILevel, kPropertyAndroidAPILevelDefault); // Add Android OS identifier if API level is defined. if (api_level != kPropertyAndroidAPILevelDefault) { std::array<uint8_t, Uuid::kNumBytes128> tmp; tmp.fill(0xc5); // any number is fine here Uuid app_uuid = Uuid::From128BitBE(tmp); tGATT_IF gatt_if = GATT_Register(app_uuid, "Ais", &ais_cback, false); GATT_StartIf(gatt_if); btgatt_db_element_t android_information_service[] = { { .uuid = ANDROID_INFORMATION_SERVICE_UUID, .type = BTGATT_DB_PRIMARY_SERVICE, }, { .uuid = GATT_UUID_AIS_API_LEVEL, .type = BTGATT_DB_CHARACTERISTIC, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ_IF_ENCRYPTED_OR_DISCOVERABLE, }}; if (GATTS_AddService(gatt_if, android_information_service, sizeof(android_information_service) / sizeof(btgatt_db_element_t)) != GATT_SERVICE_STARTED) { error("Unable to add Android Information Server gatt_if:{}", gatt_if); } attr_api_level_handle = android_information_service[1].attribute_handle; } } /* * This routine should not be called except once per stack invocation. */ void AIS_Init(void) { ais_attr_db_init(); }
system/stack/fuzzers/gatt_fuzzer.cc +3 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,9 @@ namespace os { bool GetSystemPropertyBool(const std::string& property, bool default_value) { return default_value; } uint32_t GetSystemPropertyUint32(const std::string& property, uint32_t default_value) { return default_value; } } // namespace os } // namespace bluetooth Loading