/* * Copyright 2021 HIMSA II K/S - www.himsa.com. * Represented by EHIMA - www.ehima.com * * 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 #include #include #include #include #include #include #include #include #include "bta_has_api.h" #include "btif_common.h" #include "btif_storage.h" #include "stack/include/btu.h" using base::Bind; using base::Owned; using base::Passed; using base::Unretained; using bluetooth::has::ConnectionState; using bluetooth::has::ErrorCode; using bluetooth::has::HasClientCallbacks; using bluetooth::has::HasClientInterface; using bluetooth::has::PresetInfo; using bluetooth::has::PresetInfoReason; using le_audio::has::HasClient; namespace { std::unique_ptr has_client_instance; class HearingAaccessClientServiceInterfaceImpl : public HasClientInterface, public HasClientCallbacks { ~HearingAaccessClientServiceInterfaceImpl() override = default; void Init(HasClientCallbacks* callbacks) override { DVLOG(2) << __func__; this->callbacks_ = callbacks; do_in_main_thread( FROM_HERE, Bind(&HasClient::Initialize, this, jni_thread_wrapper( FROM_HERE, Bind(&btif_storage_load_bonded_leaudio_has_devices)))); } void Connect(const RawAddress& addr) override { DVLOG(2) << __func__ << " addr: " << addr; do_in_main_thread(FROM_HERE, Bind(&HasClient::Connect, Unretained(HasClient::Get()), addr)); do_in_jni_thread( FROM_HERE, Bind(&btif_storage_set_leaudio_has_acceptlist, addr, true)); } void Disconnect(const RawAddress& addr) override { DVLOG(2) << __func__ << " addr: " << addr; do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect, Unretained(HasClient::Get()), addr)); do_in_jni_thread( FROM_HERE, Bind(&btif_storage_set_leaudio_has_acceptlist, addr, false)); } void SelectActivePreset(std::variant addr_or_group_id, uint8_t preset_index) override { DVLOG(2) << __func__ << " preset_index: " << preset_index; do_in_main_thread( FROM_HERE, Bind(&HasClient::SelectActivePreset, Unretained(HasClient::Get()), std::move(addr_or_group_id), preset_index)); } void NextActivePreset( std::variant addr_or_group_id) override { DVLOG(2) << __func__; do_in_main_thread(FROM_HERE, Bind(&HasClient::NextActivePreset, Unretained(HasClient::Get()), std::move(addr_or_group_id))); } void PreviousActivePreset( std::variant addr_or_group_id) override { DVLOG(2) << __func__; do_in_main_thread(FROM_HERE, Bind(&HasClient::PreviousActivePreset, Unretained(HasClient::Get()), std::move(addr_or_group_id))); } void GetPresetInfo(const RawAddress& addr, uint8_t preset_index) override { DVLOG(2) << __func__ << " addr: " << addr << " preset_index: " << preset_index; do_in_main_thread( FROM_HERE, Bind(&HasClient::GetPresetInfo, Unretained(HasClient::Get()), addr, preset_index)); } void SetPresetName(std::variant addr_or_group_id, uint8_t preset_index, std::string preset_name) override { DVLOG(2) << __func__ << " preset_index: " << preset_index << " preset_name: " << preset_name; do_in_main_thread( FROM_HERE, Bind(&HasClient::SetPresetName, Unretained(HasClient::Get()), std::move(addr_or_group_id), preset_index, std::move(preset_name))); } void RemoveDevice(const RawAddress& addr) override { DVLOG(2) << __func__ << " addr: " << addr; /* RemoveDevice can be called on devices that don't have BAS enabled */ if (HasClient::IsHasClientRunning()) { do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect, Unretained(HasClient::Get()), addr)); } do_in_jni_thread(FROM_HERE, Bind(&btif_storage_remove_leaudio_has, addr)); } void Cleanup(void) override { DVLOG(2) << __func__; do_in_main_thread(FROM_HERE, Bind(&HasClient::CleanUp)); } void OnConnectionState(ConnectionState state, const RawAddress& addr) override { DVLOG(2) << __func__ << " addr: " << addr; do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnConnectionState, Unretained(callbacks_), state, addr)); } void OnDeviceAvailable(const RawAddress& addr, uint8_t features) override { DVLOG(2) << __func__ << " addr: " << addr << " features: " << features; do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnDeviceAvailable, Unretained(callbacks_), addr, features)); } void OnFeaturesUpdate(const RawAddress& addr, uint8_t features) override { DVLOG(2) << __func__ << " addr: " << addr << " ha_features: " << std::bitset<8>(features); do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnFeaturesUpdate, Unretained(callbacks_), addr, features)); } void OnActivePresetSelected(std::variant addr_or_group_id, uint8_t preset_index) override { DVLOG(2) << __func__ << " preset_index: " << preset_index; do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnActivePresetSelected, Unretained(callbacks_), std::move(addr_or_group_id), preset_index)); } void OnActivePresetSelectError(std::variant addr_or_group_id, ErrorCode result_code) override { DVLOG(2) << __func__ << " result_code: " << static_cast::type>(result_code); do_in_jni_thread( FROM_HERE, Bind(&HasClientCallbacks::OnActivePresetSelectError, Unretained(callbacks_), std::move(addr_or_group_id), result_code)); } void OnPresetInfo(std::variant addr_or_group_id, PresetInfoReason change_id, std::vector detail_records) override { DVLOG(2) << __func__; for (const auto& rec : detail_records) { DVLOG(2) << "\t index: " << +rec.preset_index << ", change_id: " << (std::underlying_type::type)change_id << ", writable: " << rec.writable << ", available: " << rec.available << ", name: " << rec.preset_name; } do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnPresetInfo, Unretained(callbacks_), std::move(addr_or_group_id), change_id, std::move(detail_records))); } void OnPresetInfoError(std::variant addr_or_group_id, uint8_t preset_index, ErrorCode result_code) override { DVLOG(2) << __func__ << " result_code: " << static_cast::type>(result_code); do_in_jni_thread( FROM_HERE, Bind(&HasClientCallbacks::OnPresetInfoError, Unretained(callbacks_), std::move(addr_or_group_id), preset_index, result_code)); } void OnSetPresetNameError(std::variant addr_or_group_id, uint8_t preset_index, ErrorCode result_code) override { DVLOG(2) << __func__ << " result_code: " << static_cast::type>(result_code); do_in_jni_thread( FROM_HERE, Bind(&HasClientCallbacks::OnSetPresetNameError, Unretained(callbacks_), std::move(addr_or_group_id), preset_index, result_code)); } private: HasClientCallbacks* callbacks_; }; } /* namespace */ HasClientInterface* btif_has_client_get_interface(void) { if (!has_client_instance) has_client_instance.reset(new HearingAaccessClientServiceInterfaceImpl()); return has_client_instance.get(); }