1 /*
2 * Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3 * www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <base/logging.h>
19 #include <hardware/bluetooth.h>
20 #include <hardware/bt_le_audio.h>
21
22 #include <vector>
23
24 #include "bta_le_audio_api.h"
25 #include "btif_common.h"
26 #include "btif_storage.h"
27 #include "stack/include/btu.h"
28
29 using base::Bind;
30 using base::Unretained;
31 using bluetooth::le_audio::btle_audio_codec_config_t;
32 using bluetooth::le_audio::ConnectionState;
33 using bluetooth::le_audio::GroupNodeStatus;
34 using bluetooth::le_audio::GroupStatus;
35 using bluetooth::le_audio::LeAudioClientCallbacks;
36 using bluetooth::le_audio::LeAudioClientInterface;
37
38 namespace {
39 class LeAudioClientInterfaceImpl;
40 std::unique_ptr<LeAudioClientInterface> leAudioInstance;
41
42 class LeAudioClientInterfaceImpl : public LeAudioClientInterface,
43 public LeAudioClientCallbacks {
44 ~LeAudioClientInterfaceImpl() = default;
45
OnInitialized(void)46 void OnInitialized(void) {
47 do_in_jni_thread(FROM_HERE, Bind(&LeAudioClientCallbacks::OnInitialized,
48 Unretained(callbacks)));
49 }
50
OnConnectionState(ConnectionState state,const RawAddress & address)51 void OnConnectionState(ConnectionState state,
52 const RawAddress& address) override {
53 do_in_jni_thread(FROM_HERE, Bind(&LeAudioClientCallbacks::OnConnectionState,
54 Unretained(callbacks), state, address));
55 }
56
OnGroupStatus(int group_id,GroupStatus group_status)57 void OnGroupStatus(int group_id, GroupStatus group_status) override {
58 do_in_jni_thread(FROM_HERE,
59 Bind(&LeAudioClientCallbacks::OnGroupStatus,
60 Unretained(callbacks), group_id, group_status));
61 }
62
OnGroupNodeStatus(const RawAddress & addr,int group_id,GroupNodeStatus node_status)63 void OnGroupNodeStatus(const RawAddress& addr, int group_id,
64 GroupNodeStatus node_status) override {
65 do_in_jni_thread(FROM_HERE,
66 Bind(&LeAudioClientCallbacks::OnGroupNodeStatus,
67 Unretained(callbacks), addr, group_id, node_status));
68 }
69
OnAudioConf(uint8_t direction,int group_id,uint32_t snk_audio_location,uint32_t src_audio_location,uint16_t avail_cont)70 void OnAudioConf(uint8_t direction, int group_id, uint32_t snk_audio_location,
71 uint32_t src_audio_location, uint16_t avail_cont) override {
72 do_in_jni_thread(FROM_HERE,
73 Bind(&LeAudioClientCallbacks::OnAudioConf,
74 Unretained(callbacks), direction, group_id,
75 snk_audio_location, src_audio_location, avail_cont));
76 }
77
OnSinkAudioLocationAvailable(const RawAddress & address,uint32_t snk_audio_location)78 void OnSinkAudioLocationAvailable(const RawAddress& address,
79 uint32_t snk_audio_location) override {
80 do_in_jni_thread(FROM_HERE,
81 Bind(&LeAudioClientCallbacks::OnSinkAudioLocationAvailable,
82 Unretained(callbacks), address, snk_audio_location));
83 }
84
OnAudioLocalCodecCapabilities(std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf)85 void OnAudioLocalCodecCapabilities(
86 std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
87 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf)
88 override {
89 do_in_jni_thread(
90 FROM_HERE, Bind(&LeAudioClientCallbacks::OnAudioLocalCodecCapabilities,
91 Unretained(callbacks), local_input_capa_codec_conf,
92 local_output_capa_codec_conf));
93 }
94
OnAudioGroupCodecConf(int group_id,btle_audio_codec_config_t input_codec_conf,btle_audio_codec_config_t output_codec_conf,std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,std::vector<btle_audio_codec_config_t> output_selectable_codec_conf)95 void OnAudioGroupCodecConf(
96 int group_id, btle_audio_codec_config_t input_codec_conf,
97 btle_audio_codec_config_t output_codec_conf,
98 std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
99 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf)
100 override {
101 do_in_jni_thread(FROM_HERE,
102 Bind(&LeAudioClientCallbacks::OnAudioGroupCodecConf,
103 Unretained(callbacks), group_id, input_codec_conf,
104 output_codec_conf, input_selectable_codec_conf,
105 output_selectable_codec_conf));
106 }
107
Initialize(LeAudioClientCallbacks * callbacks,const std::vector<btle_audio_codec_config_t> & offloading_preference)108 void Initialize(LeAudioClientCallbacks* callbacks,
109 const std::vector<btle_audio_codec_config_t>&
110 offloading_preference) override {
111 this->callbacks = callbacks;
112
113 for (auto codec : offloading_preference) {
114 LOG_INFO("supported codec: %s", codec.ToString().c_str());
115 }
116
117 LeAudioClient::InitializeAudioSetConfigurationProvider();
118 do_in_main_thread(
119 FROM_HERE, Bind(&LeAudioClient::Initialize, this,
120 jni_thread_wrapper(
121 FROM_HERE, Bind(&btif_storage_load_bonded_leaudio)),
122 base::Bind([]() -> bool {
123 return LeAudioHalVerifier::SupportsLeAudio();
124 }),
125 offloading_preference));
126 }
127
Cleanup(void)128 void Cleanup(void) override {
129 DVLOG(2) << __func__;
130 do_in_main_thread(
131 FROM_HERE,
132 Bind(&LeAudioClient::Cleanup,
133 jni_thread_wrapper(
134 FROM_HERE,
135 Bind(&LeAudioClient::CleanupAudioSetConfigurationProvider))));
136 }
137
RemoveDevice(const RawAddress & address)138 void RemoveDevice(const RawAddress& address) override {
139 DVLOG(2) << __func__ << " address: " << address;
140 do_in_main_thread(FROM_HERE,
141 Bind(&LeAudioClient::RemoveDevice,
142 Unretained(LeAudioClient::Get()), address));
143
144 do_in_jni_thread(FROM_HERE, Bind(&btif_storage_remove_leaudio, address));
145 }
146
Connect(const RawAddress & address)147 void Connect(const RawAddress& address) override {
148 DVLOG(2) << __func__ << " address: " << address;
149 do_in_main_thread(FROM_HERE,
150 Bind(&LeAudioClient::Connect,
151 Unretained(LeAudioClient::Get()), address));
152 }
153
Disconnect(const RawAddress & address)154 void Disconnect(const RawAddress& address) override {
155 DVLOG(2) << __func__ << " address: " << address;
156 do_in_main_thread(FROM_HERE,
157 Bind(&LeAudioClient::Disconnect,
158 Unretained(LeAudioClient::Get()), address));
159 }
160
GroupAddNode(const int group_id,const RawAddress & address)161 void GroupAddNode(const int group_id, const RawAddress& address) override {
162 DVLOG(2) << __func__ << " group_id: " << group_id
163 << " address: " << address;
164 do_in_main_thread(
165 FROM_HERE, Bind(&LeAudioClient::GroupAddNode,
166 Unretained(LeAudioClient::Get()), group_id, address));
167 }
168
GroupRemoveNode(const int group_id,const RawAddress & address)169 void GroupRemoveNode(const int group_id, const RawAddress& address) override {
170 DVLOG(2) << __func__ << " group_id: " << group_id
171 << " address: " << address;
172 do_in_main_thread(
173 FROM_HERE, Bind(&LeAudioClient::GroupRemoveNode,
174 Unretained(LeAudioClient::Get()), group_id, address));
175 }
176
GroupSetActive(const int group_id)177 void GroupSetActive(const int group_id) override {
178 DVLOG(2) << __func__ << " group_id: " << group_id;
179 do_in_main_thread(FROM_HERE,
180 Bind(&LeAudioClient::GroupSetActive,
181 Unretained(LeAudioClient::Get()), group_id));
182 }
183
SetCodecConfigPreference(int group_id,btle_audio_codec_config_t input_codec_config,btle_audio_codec_config_t output_codec_config)184 void SetCodecConfigPreference(int group_id,
185 btle_audio_codec_config_t input_codec_config,
186 btle_audio_codec_config_t output_codec_config) {
187 DVLOG(2) << __func__ << " group_id: " << group_id;
188 do_in_main_thread(FROM_HERE,
189 Bind(&LeAudioClient::SetCodecConfigPreference,
190 Unretained(LeAudioClient::Get()), group_id,
191 input_codec_config, output_codec_config));
192 }
193
SetCcidInformation(int ccid,int context_type)194 void SetCcidInformation(int ccid, int context_type) {
195 DVLOG(2) << __func__ << " ccid: " << ccid << " context_type"
196 << context_type;
197 do_in_main_thread(
198 FROM_HERE, Bind(&LeAudioClient::SetCcidInformation,
199 Unretained(LeAudioClient::Get()), ccid, context_type));
200 }
201
SetInCall(bool in_call)202 void SetInCall(bool in_call) {
203 DVLOG(2) << __func__ << " in_call: " << in_call;
204 do_in_main_thread(FROM_HERE,
205 Bind(&LeAudioClient::SetInCall,
206 Unretained(LeAudioClient::Get()), in_call));
207 }
208
209 private:
210 LeAudioClientCallbacks* callbacks;
211 };
212
213 } /* namespace */
214
btif_le_audio_get_interface()215 LeAudioClientInterface* btif_le_audio_get_interface() {
216 if (!leAudioInstance) {
217 leAudioInstance.reset(new LeAudioClientInterfaceImpl());
218 }
219
220 return leAudioInstance.get();
221 }
222