/*
* 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_profile_storage.h"
#include "stack/include/main_thread.h"
#include "types/raw_address.h"
// TODO(b/369381361) Enfore -Wmissing-prototypes
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
using base::Bind;
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 bluetooth::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 {
this->callbacks_ = callbacks;
do_in_main_thread(
Bind(&HasClient::Initialize, this,
jni_thread_wrapper(Bind(&btif_storage_load_bonded_leaudio_has_devices))));
}
void Connect(const RawAddress& addr) override {
do_in_main_thread(Bind(&HasClient::Connect, Unretained(HasClient::Get()), addr));
do_in_jni_thread(Bind(&btif_storage_set_leaudio_has_acceptlist, addr, true));
}
void Disconnect(const RawAddress& addr) override {
do_in_main_thread(Bind(&HasClient::Disconnect, Unretained(HasClient::Get()), addr));
do_in_jni_thread(Bind(&btif_storage_set_leaudio_has_acceptlist, addr, false));
}
void SelectActivePreset(std::variant addr_or_group_id,
uint8_t preset_index) override {
do_in_main_thread(Bind(&HasClient::SelectActivePreset, Unretained(HasClient::Get()),
std::move(addr_or_group_id), preset_index));
}
void NextActivePreset(std::variant addr_or_group_id) override {
do_in_main_thread(Bind(&HasClient::NextActivePreset, Unretained(HasClient::Get()),
std::move(addr_or_group_id)));
}
void PreviousActivePreset(std::variant addr_or_group_id) override {
do_in_main_thread(Bind(&HasClient::PreviousActivePreset, Unretained(HasClient::Get()),
std::move(addr_or_group_id)));
}
void GetPresetInfo(const RawAddress& addr, uint8_t preset_index) override {
do_in_main_thread(
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 {
do_in_main_thread(Bind(&HasClient::SetPresetName, Unretained(HasClient::Get()),
std::move(addr_or_group_id), preset_index, std::move(preset_name)));
}
void RemoveDevice(const RawAddress& addr) override {
/* RemoveDevice can be called on devices that don't have BAS enabled */
if (HasClient::IsHasClientRunning()) {
do_in_main_thread(Bind(&HasClient::Disconnect, Unretained(HasClient::Get()), addr));
}
do_in_jni_thread(Bind(&btif_storage_remove_leaudio_has, addr));
}
void Cleanup(void) override { do_in_main_thread(Bind(&HasClient::CleanUp)); }
void OnConnectionState(ConnectionState state, const RawAddress& addr) override {
do_in_jni_thread(
Bind(&HasClientCallbacks::OnConnectionState, Unretained(callbacks_), state, addr));
}
void OnDeviceAvailable(const RawAddress& addr, uint8_t features) override {
do_in_jni_thread(
Bind(&HasClientCallbacks::OnDeviceAvailable, Unretained(callbacks_), addr, features));
}
void OnFeaturesUpdate(const RawAddress& addr, uint8_t features) override {
do_in_jni_thread(
Bind(&HasClientCallbacks::OnFeaturesUpdate, Unretained(callbacks_), addr, features));
}
void OnActivePresetSelected(std::variant addr_or_group_id,
uint8_t preset_index) override {
do_in_jni_thread(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 {
do_in_jni_thread(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 {
do_in_jni_thread(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 {
do_in_jni_thread(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 {
do_in_jni_thread(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();
}