/*
* 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 "bind_helpers.h"
#include "bta_csis_api.h"
#include "btif_common.h"
#include "btif_profile_storage.h"
#include "stack/include/main_thread.h"
#include "types/bluetooth/uuid.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::csis::ConnectionState;
using bluetooth::csis::CsisClientCallbacks;
using bluetooth::csis::CsisClientInterface;
using bluetooth::csis::CsisGroupLockStatus;
using bluetooth::csis::CsisClient;
using namespace bluetooth;
namespace {
std::unique_ptr csis_client_instance;
std::atomic_bool initialized = false;
class CsipSetCoordinatorServiceInterfaceImpl : public CsisClientInterface,
public CsisClientCallbacks {
~CsipSetCoordinatorServiceInterfaceImpl() override = default;
void Init(CsisClientCallbacks* callbacks) override {
this->callbacks_ = callbacks;
do_in_main_thread(Bind(&CsisClient::Initialize, this,
jni_thread_wrapper(Bind(&btif_storage_load_bonded_csis_devices))));
/* It might be not yet initialized, but setting this flag here is safe,
* because other calls will check this and the native instance
*/
initialized = true;
}
void Connect(const RawAddress& addr) override {
if (!initialized || !CsisClient::IsCsisClientRunning()) {
log::verbose(
"call ignored, due to already started cleanup procedure or service "
"being not read");
return;
}
do_in_main_thread(Bind(&CsisClient::Connect, Unretained(CsisClient::Get()), addr));
}
void Disconnect(const RawAddress& addr) override {
if (!initialized || !CsisClient::IsCsisClientRunning()) {
log::verbose(
"call ignored, due to already started cleanup procedure or service "
"being not read");
return;
}
do_in_main_thread(Bind(&CsisClient::Disconnect, Unretained(CsisClient::Get()), addr));
}
void RemoveDevice(const RawAddress& addr) override {
if (!initialized || !CsisClient::IsCsisClientRunning()) {
log::verbose(
"call ignored, due to already started cleanup procedure or service "
"being not ready");
/* Clear storage */
do_in_jni_thread(Bind(&btif_storage_remove_csis_device, addr));
return;
}
do_in_main_thread(Bind(&CsisClient::RemoveDevice, Unretained(CsisClient::Get()), addr));
/* Clear storage */
do_in_jni_thread(Bind(&btif_storage_remove_csis_device, addr));
}
void LockGroup(int group_id, bool lock) override {
if (!initialized || !CsisClient::IsCsisClientRunning()) {
log::verbose(
"call ignored, due to already started cleanup procedure or service "
"being not read");
return;
}
do_in_main_thread(Bind(&CsisClient::LockGroup, Unretained(CsisClient::Get()), group_id, lock,
base::DoNothing()));
}
void Cleanup(void) override {
if (!initialized || !CsisClient::IsCsisClientRunning()) {
log::verbose(
"call ignored, due to already started cleanup procedure or service "
"being not read");
return;
}
initialized = false;
do_in_main_thread(Bind(&CsisClient::CleanUp));
}
void OnConnectionState(const RawAddress& addr, ConnectionState state) override {
do_in_jni_thread(
Bind(&CsisClientCallbacks::OnConnectionState, Unretained(callbacks_), addr, state));
}
void OnDeviceAvailable(const RawAddress& addr, int group_id, int group_size, int rank,
const bluetooth::Uuid& uuid) override {
do_in_jni_thread(Bind(&CsisClientCallbacks::OnDeviceAvailable, Unretained(callbacks_), addr,
group_id, group_size, rank, uuid));
}
void OnSetMemberAvailable(const RawAddress& addr, int group_id) override {
do_in_jni_thread(Bind(&CsisClientCallbacks::OnSetMemberAvailable, Unretained(callbacks_), addr,
group_id));
}
/* Callback for lock changed in the group */
virtual void OnGroupLockChanged(int group_id, bool locked, CsisGroupLockStatus status) override {
do_in_jni_thread(Bind(&CsisClientCallbacks::OnGroupLockChanged, Unretained(callbacks_),
group_id, locked, status));
}
private:
CsisClientCallbacks* callbacks_;
};
} /* namespace */
CsisClientInterface* btif_csis_client_get_interface(void) {
if (!csis_client_instance) {
csis_client_instance.reset(new CsipSetCoordinatorServiceInterfaceImpl());
}
return csis_client_instance.get();
}