summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Zhengping Jiang <jiangzp@google.com> 2024-08-02 17:09:45 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2024-08-02 17:09:45 +0000
commitcb5774b5b057de01a6b1aad919ac272d0caa0d19 (patch)
treeb42aa617071caf3a78ec2562094659f82cdd37fd
parent3556b136ad4f583f417f47339c546cc139a16814 (diff)
parent26b76ebcb79645522b5a6f01671e5be5a3500e3c (diff)
Merge "Add Android information service to send API level" into main
-rw-r--r--system/btif/src/stack_manager.cc2
-rw-r--r--system/stack/Android.bp5
-rw-r--r--system/stack/BUILD.gn2
-rw-r--r--system/stack/ais/ais_ble.cc144
-rw-r--r--system/stack/fuzzers/gatt_fuzzer.cc3
-rw-r--r--system/stack/gatt/gatt_api.cc7
-rw-r--r--system/stack/include/ais_api.h43
-rw-r--r--system/test/mock/mock_stack_ais_ble.cc20
8 files changed, 224 insertions, 2 deletions
diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc
index 3af74062d6..61099d65d8 100644
--- a/system/btif/src/stack_manager.cc
+++ b/system/btif/src/stack_manager.cc
@@ -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
@@ -301,6 +302,7 @@ static void event_start_up_stack(bluetooth::core::CoreInterface* interface,
RFCOMM_Init();
GAP_Init();
+ AIS_Init();
startProfiles();
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index 1d6376c90d..d6c88e0dfa 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -38,6 +38,7 @@ cc_library_static {
name: "libbt-stack",
defaults: ["fluoride_defaults"],
local_include_dirs: [
+ "ais",
"avct",
"avdt",
"avrc",
@@ -180,6 +181,7 @@ cc_library_static {
name: "libbt-stack-core",
defaults: ["fluoride_defaults"],
local_include_dirs: [
+ "ais",
"avct",
"avdt",
"avrc",
@@ -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",
@@ -517,6 +520,7 @@ cc_fuzz {
":TestMockStackL2cap",
":TestMockStackMetrics",
":TestMockStackSdp",
+ "ais/*.cc",
"eatt/*.cc",
"fuzzers/gatt_fuzzer.cc",
"gatt/*.cc",
@@ -1973,6 +1977,7 @@ cc_test {
":TestMockStackL2cap",
":TestMockStackSdp",
":TestMockStackSmp",
+ "ais/ais_ble.cc",
"arbiter/acl_arbiter.cc",
"eatt/eatt.cc",
"gatt/att_protocol.cc",
diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn
index 2581035379..68d5136db0 100644
--- a/system/stack/BUILD.gn
+++ b/system/stack/BUILD.gn
@@ -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",
@@ -187,6 +188,7 @@ source_set("stack") {
include_dirs = [
".",
"include",
+ "ais",
"avct",
"btm",
"avrc",
diff --git a/system/stack/ais/ais_ble.cc b/system/stack/ais/ais_ble.cc
new file mode 100644
index 0000000000..f545fc7981
--- /dev/null
+++ b/system/stack/ais/ais_ble.cc
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * 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(); }
diff --git a/system/stack/fuzzers/gatt_fuzzer.cc b/system/stack/fuzzers/gatt_fuzzer.cc
index a98f674e72..409e62c1da 100644
--- a/system/stack/fuzzers/gatt_fuzzer.cc
+++ b/system/stack/fuzzers/gatt_fuzzer.cc
@@ -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
diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc
index c6ea0cf5b0..dff5e42974 100644
--- a/system/stack/gatt/gatt_api.cc
+++ b/system/stack/gatt/gatt_api.cc
@@ -41,6 +41,7 @@
#include "stack/btm/btm_dev.h"
#include "stack/gatt/connection_manager.h"
#include "stack/gatt/gatt_int.h"
+#include "stack/include/ais_api.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/l2cap_acl_interface.h"
@@ -323,8 +324,10 @@ tGATT_STATUS GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, in
Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
if (*p_uuid != Uuid::From16Bit(UUID_SERVCLASS_GMCS_SERVER) &&
*p_uuid != Uuid::From16Bit(UUID_SERVCLASS_GTBS_SERVER)) {
- if (com::android::bluetooth::flags::channel_sounding_in_stack() &&
- *p_uuid == Uuid::From16Bit(UUID_SERVCLASS_RAS)) {
+ if ((com::android::bluetooth::flags::channel_sounding_in_stack() &&
+ *p_uuid == Uuid::From16Bit(UUID_SERVCLASS_RAS)) ||
+ (com::android::bluetooth::flags::android_os_identifier() &&
+ *p_uuid == ANDROID_INFORMATION_SERVICE_UUID)) {
elem.sdp_handle = 0;
} else {
elem.sdp_handle = gatt_add_sdp_record(*p_uuid, elem.s_hdl, elem.e_hdl);
diff --git a/system/stack/include/ais_api.h b/system/stack/include/ais_api.h
new file mode 100644
index 0000000000..41dad8242b
--- /dev/null
+++ b/system/stack/include/ais_api.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#ifndef SYSTEM_STACK_INCLUDE_AIS_API_H_
+#define SYSTEM_STACK_INCLUDE_AIS_API_H_
+
+#include "types/bluetooth/uuid.h"
+
+#define ANDROID_INFORMATION_SERVICE_UUID_STRING "e73e0001-ef1b-4e74-8291-2e4f3164f3b5"
+/* Android Information Service characteristic */
+#define GATT_UUID_AIS_API_LEVEL_STRING "e73e0002-ef1b-4e74-8291-2e4f3164f3b5"
+
+extern const bluetooth::Uuid ANDROID_INFORMATION_SERVICE_UUID;
+extern const bluetooth::Uuid GATT_UUID_AIS_API_LEVEL;
+
+/*******************************************************************************
+ *
+ * Function AIS_Init
+ *
+ * Description Initializes the control blocks used by AIS.
+ * This routine should not be called except once per
+ * stack invocation.
+ *
+ * Returns Nothing
+ *
+ ******************************************************************************/
+void AIS_Init(void);
+
+#endif // SYSTEM_STACK_INCLUDE_AIS_API_H_
diff --git a/system/test/mock/mock_stack_ais_ble.cc b/system/test/mock/mock_stack_ais_ble.cc
new file mode 100644
index 0000000000..29630207b4
--- /dev/null
+++ b/system/test/mock/mock_stack_ais_ble.cc
@@ -0,0 +1,20 @@
+/*
+ * 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 "stack/include/ais_api.h"
+#include "test/common/mock_functions.h"
+
+void AIS_Init(void) { inc_func_call_count(__func__); }