// Copyright 2022, 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 "gatt_shim.h" #include #include #include #include #include #include "include/hardware/bluetooth.h" #include "include/hardware/bt_common_types.h" #include "include/hardware/bt_gatt_client.h" #include "include/hardware/bt_gatt_server.h" #include "os/log.h" #include "rust/cxx.h" #include "stack/include/gatt_api.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" bt_status_t do_in_jni_thread(base::OnceClosure task); namespace { std::optional AddressOfConnection(uint16_t conn_id) { tGATT_IF gatt_if; RawAddress remote_bda; tBT_TRANSPORT transport; auto valid = GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport); if (!valid) { return std::nullopt; } return remote_bda; } } // namespace namespace bluetooth { namespace gatt { void GattServerCallbacks::OnServerRead(uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle, AttributeBackingType attr_type, uint32_t offset, bool is_long) const { auto addr = AddressOfConnection(conn_id); if (!addr.has_value()) { log::warn( "Dropping server read characteristic since connection {} not found", conn_id); return; } switch (attr_type) { case AttributeBackingType::CHARACTERISTIC: do_in_jni_thread(base::BindOnce(callbacks.request_read_characteristic_cb, conn_id, trans_id, addr.value(), attr_handle, offset, is_long)); break; case AttributeBackingType::DESCRIPTOR: do_in_jni_thread(base::BindOnce(callbacks.request_read_descriptor_cb, conn_id, trans_id, addr.value(), attr_handle, offset, is_long)); break; default: log::fatal("Unexpected backing type {}", attr_type); } } static void request_write_with_vec(request_write_callback cb, int conn_id, int trans_id, const RawAddress& bda, int attr_handle, int offset, bool need_rsp, bool is_prep, const std::vector& value) { cb(conn_id, trans_id, bda, attr_handle, offset, need_rsp, is_prep, value.data(), value.size()); } void GattServerCallbacks::OnServerWrite( uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle, AttributeBackingType attr_type, uint32_t offset, bool need_response, bool is_prepare, ::rust::Slice value) const { auto addr = AddressOfConnection(conn_id); if (!addr.has_value()) { log::warn( "Dropping server write characteristic since connection {} not found", conn_id); return; } auto buf = std::vector(value.begin(), value.end()); switch (attr_type) { case AttributeBackingType::CHARACTERISTIC: do_in_jni_thread(base::BindOnce( request_write_with_vec, callbacks.request_write_characteristic_cb, conn_id, trans_id, addr.value(), attr_handle, offset, need_response, is_prepare, std::move(buf))); break; case AttributeBackingType::DESCRIPTOR: do_in_jni_thread(base::BindOnce( request_write_with_vec, callbacks.request_write_descriptor_cb, conn_id, trans_id, addr.value(), attr_handle, offset, need_response, is_prepare, std::move(buf))); break; default: log::fatal("Unexpected backing type {}", attr_type); } } void GattServerCallbacks::OnIndicationSentConfirmation(uint16_t conn_id, int status) const { do_in_jni_thread( base::BindOnce(callbacks.indication_sent_cb, conn_id, status)); } void GattServerCallbacks::OnExecute(uint16_t conn_id, uint32_t trans_id, bool execute) const { auto addr = AddressOfConnection(conn_id); if (!addr.has_value()) { log::warn("Dropping server execute write since connection {} not found", conn_id); return; } do_in_jni_thread(base::BindOnce(callbacks.request_exec_write_cb, conn_id, trans_id, addr.value(), execute)); } } // namespace gatt } // namespace bluetooth