unplugged-vendor/system/bt/btif/src/btif_le_audio.cc

335 lines
11 KiB
C++
Raw Normal View History

/*
* Copyright 2019 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 <hardware/bluetooth.h>
#include <vector>
#include "mediatek/bta/include/mtk_bta_le_audio_api.h"
#include "btif_common.h"
#include "btif_storage.h"
#include "hardware/bt_le_audio.h"
#include "stack/include/btu.h"
#include "osi/include/properties.h"
#include <hardware/bt_le_audio.h>
using base::Bind;
using base::Unretained;
using bluetooth::le_audio::ConnectionState;
using bluetooth::le_audio::GroupLockStatus;
using bluetooth::le_audio::GroupNodeStatus;
using bluetooth::le_audio::GroupStatus;
using bluetooth::le_audio::LeAudioClientCallbacks;
using bluetooth::le_audio::LeAudioClientInterface;
static char prop_leaudio[PROPERTY_VALUE_MAX];
namespace {
class LeAudioClientInterfaceImpl;
std::unique_ptr<LeAudioClientInterface> lEAudioInstance;
class LeAudioClientInterfaceImpl : public LeAudioClientInterface,
public LeAudioClientCallbacks {
~LeAudioClientInterfaceImpl() = default;
void OnConnectionState(ConnectionState state,
const RawAddress& address) override {
DVLOG(2) << __func__ << " address: " << address;
do_in_jni_thread(FROM_HERE, Bind(&LeAudioClientCallbacks::OnConnectionState,
Unretained(callbacks), state, address));
}
void OnGroupStatus(uint8_t group_id, GroupStatus group_status,
uint8_t group_flags) override {
do_in_jni_thread(FROM_HERE, Bind(&LeAudioClientCallbacks::OnGroupStatus,
Unretained(callbacks), group_id,
group_status, group_flags));
}
void OnGroupNodeStatus(const RawAddress& addr, uint8_t group_id,
GroupNodeStatus node_status) override {
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioClientCallbacks::OnGroupNodeStatus,
Unretained(callbacks), addr, group_id, node_status));
}
void OnSetMemberAvailable(const RawAddress& address,
uint8_t group_id) override {
DVLOG(2) << __func__ << " address: " << address
<< ", group_id: " << group_id;
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioClientCallbacks::OnSetMemberAvailable,
Unretained(callbacks), address, group_id));
}
void OnGroupLockChanged(uint8_t group_id, bool locked,
GroupLockStatus status) override {
DVLOG(2) << __func__ << " group id: " << group_id
<< ", locked: " << int(locked) << ", status: " << int(status);
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioClientCallbacks::OnGroupLockChanged,
Unretained(callbacks), group_id, locked, status));
}
void OnAudioConf(const RawAddress& addr, uint8_t direction, uint8_t group_id,
uint32_t snk_audio_location,
uint32_t src_audio_location) override {
do_in_jni_thread(
FROM_HERE,
Bind(&LeAudioClientCallbacks::OnAudioConf, Unretained(callbacks), addr,
direction, group_id, snk_audio_location, src_audio_location));
}
void Initialize(LeAudioClientCallbacks* callbacks) override {
this->callbacks = callbacks;
do_in_main_thread(
FROM_HERE,
Bind(&LeAudioClient::Initialize, this,
jni_thread_wrapper(FROM_HERE,
Bind(&btif_storage_load_bonded_leaudio))));
}
void Cleanup(void) override {
do_in_main_thread(FROM_HERE, Bind(&LeAudioClient::Cleanup));
}
void Connect(const RawAddress& address) override {
DVLOG(2) << __func__ << " address: " << address;
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::Connect,
Unretained(LeAudioClient::Get()), address));
}
void Disconnect(const RawAddress& address) override {
DVLOG(2) << __func__ << " address: " << address;
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::Disconnect,
Unretained(LeAudioClient::Get()), address));
do_in_jni_thread(FROM_HERE,
Bind(&btif_storage_remove_leaudio_white_list, address));
}
void Forget(const RawAddress& address) override {}
void GroupAddNode(const uint8_t group_id, const RawAddress& addr) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupAddNode,
Unretained(LeAudioClient::Get()), group_id, addr));
}
void GroupRemoveNode(const uint8_t group_id,
const RawAddress& addr) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupRemoveNode,
Unretained(LeAudioClient::Get()), group_id, addr));
}
void GroupStream(const uint8_t group_id) override {
do_in_main_thread(FROM_HERE, Bind(&LeAudioClient::GroupStream,
Unretained(LeAudioClient::Get()), group_id));
}
void GroupSuspend(const uint8_t group_id) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupSuspend,
Unretained(LeAudioClient::Get()), group_id));
}
void GroupStart(const uint8_t group_id) override {
do_in_main_thread(FROM_HERE, Bind(&LeAudioClient::GroupStart,
Unretained(LeAudioClient::Get()), group_id));
}
void GroupStop(const uint8_t group_id) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupStop,
Unretained(LeAudioClient::Get()), group_id));
}
void GroupLockSet(const uint8_t group_id, bool lock) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupLockSet,
Unretained(LeAudioClient::Get()), group_id, lock));
}
void GroupDestroy(const uint8_t group_id) override {
do_in_main_thread(FROM_HERE,
Bind(&LeAudioClient::GroupDestroy,
Unretained(LeAudioClient::Get()), group_id));
}
private:
LeAudioClientCallbacks* callbacks;
};
} /* namespace */
LeAudioClientInterface* LeAudioInstance() {
if (!lEAudioInstance) {
lEAudioInstance.reset(new LeAudioClientInterfaceImpl());
}
return lEAudioInstance.get();
}
static bt_status_t init(LeAudioClientCallbacks* callbacks) {
osi_property_get(PROPERTY_LEAUDIO, prop_leaudio, "");
LOG_INFO("%s: prop_leaudio = %s", __func__, prop_leaudio);
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->Initialize(callbacks);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static void cleanup(void) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0)
LeAudioInstance()->Cleanup();
else
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
}
static bt_status_t connect(const RawAddress* bd_addr) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->Connect(*bd_addr);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t disconnect(const RawAddress* bd_addr) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->Disconnect(*bd_addr);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t forget(const RawAddress* bd_addr) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->Forget(*bd_addr);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_add_node(const uint8_t group_id, const RawAddress* bd_addr) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupAddNode(group_id, *bd_addr);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_remove_node(const uint8_t group_id, const RawAddress* bd_addr) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupRemoveNode(group_id, *bd_addr);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_stream(const uint8_t group_id) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupStream(group_id);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_suspend(const uint8_t group_id) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupSuspend(group_id);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_start(const uint8_t group_id) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupStart(group_id);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_stop(const uint8_t group_id) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupStop(group_id);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_lock_set(const uint8_t group_id, bool lock) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupLockSet(group_id, lock);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
static bt_status_t group_destroy(const uint8_t group_id) {
if (strcmp(prop_leaudio, "ums") == 0 || strcmp(prop_leaudio, "ums-cg") == 0) {
LeAudioInstance()->GroupDestroy(group_id);
return BT_STATUS_SUCCESS;
} else {
LOG_INFO("%s: prop_leaudio doesn't support", __func__);
return BT_STATUS_FAIL;
}
}
EXPORT_SYMBOL bleaudio_interface_t bleaudioInterface = {
sizeof(bleaudioInterface),
init,
cleanup,
connect,
disconnect,
forget,
group_add_node,
group_remove_node,
group_stream,
group_suspend,
group_start,
group_stop,
group_lock_set,
group_destroy,
};