1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - 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/bind_helpers.h>
19 #include <base/functional/bind.h>
20 #include <base/location.h>
21 #include <base/logging.h>
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_has.h>
24
25 #include <bitset>
26 #include <string>
27 #include <vector>
28
29 #include "bta_has_api.h"
30 #include "btif_common.h"
31 #include "btif_profile_storage.h"
32 #include "stack/include/btu.h"
33
34 using base::Bind;
35 using base::Owned;
36 using base::Passed;
37 using base::Unretained;
38 using bluetooth::has::ConnectionState;
39 using bluetooth::has::ErrorCode;
40 using bluetooth::has::HasClientCallbacks;
41 using bluetooth::has::HasClientInterface;
42 using bluetooth::has::PresetInfo;
43 using bluetooth::has::PresetInfoReason;
44
45 using le_audio::has::HasClient;
46
47 namespace {
48 std::unique_ptr<HasClientInterface> has_client_instance;
49
50 class HearingAaccessClientServiceInterfaceImpl : public HasClientInterface,
51 public HasClientCallbacks {
52 ~HearingAaccessClientServiceInterfaceImpl() override = default;
53
Init(HasClientCallbacks * callbacks)54 void Init(HasClientCallbacks* callbacks) override {
55 DVLOG(2) << __func__;
56 this->callbacks_ = callbacks;
57
58 do_in_main_thread(
59 FROM_HERE,
60 Bind(&HasClient::Initialize, this,
61 jni_thread_wrapper(
62 FROM_HERE,
63 Bind(&btif_storage_load_bonded_leaudio_has_devices))));
64 }
65
Connect(const RawAddress & addr)66 void Connect(const RawAddress& addr) override {
67 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr);
68 do_in_main_thread(FROM_HERE, Bind(&HasClient::Connect,
69 Unretained(HasClient::Get()), addr));
70
71 do_in_jni_thread(
72 FROM_HERE, Bind(&btif_storage_set_leaudio_has_acceptlist, addr, true));
73 }
74
Disconnect(const RawAddress & addr)75 void Disconnect(const RawAddress& addr) override {
76 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr);
77 do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect,
78 Unretained(HasClient::Get()), addr));
79
80 do_in_jni_thread(
81 FROM_HERE, Bind(&btif_storage_set_leaudio_has_acceptlist, addr, false));
82 }
83
SelectActivePreset(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index)84 void SelectActivePreset(std::variant<RawAddress, int> addr_or_group_id,
85 uint8_t preset_index) override {
86 DVLOG(2) << __func__ << " preset_index: " << preset_index;
87
88 do_in_main_thread(
89 FROM_HERE,
90 Bind(&HasClient::SelectActivePreset, Unretained(HasClient::Get()),
91 std::move(addr_or_group_id), preset_index));
92 }
93
NextActivePreset(std::variant<RawAddress,int> addr_or_group_id)94 void NextActivePreset(
95 std::variant<RawAddress, int> addr_or_group_id) override {
96 DVLOG(2) << __func__;
97
98 do_in_main_thread(FROM_HERE, Bind(&HasClient::NextActivePreset,
99 Unretained(HasClient::Get()),
100 std::move(addr_or_group_id)));
101 }
102
PreviousActivePreset(std::variant<RawAddress,int> addr_or_group_id)103 void PreviousActivePreset(
104 std::variant<RawAddress, int> addr_or_group_id) override {
105 DVLOG(2) << __func__;
106
107 do_in_main_thread(FROM_HERE, Bind(&HasClient::PreviousActivePreset,
108 Unretained(HasClient::Get()),
109 std::move(addr_or_group_id)));
110 }
111
GetPresetInfo(const RawAddress & addr,uint8_t preset_index)112 void GetPresetInfo(const RawAddress& addr, uint8_t preset_index) override {
113 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr)
114 << " preset_index: " << preset_index;
115
116 do_in_main_thread(
117 FROM_HERE, Bind(&HasClient::GetPresetInfo, Unretained(HasClient::Get()),
118 addr, preset_index));
119 }
120
SetPresetName(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,std::string preset_name)121 void SetPresetName(std::variant<RawAddress, int> addr_or_group_id,
122 uint8_t preset_index, std::string preset_name) override {
123 DVLOG(2) << __func__ << " preset_index: " << preset_index
124 << " preset_name: " << preset_name;
125
126 do_in_main_thread(
127 FROM_HERE, Bind(&HasClient::SetPresetName, Unretained(HasClient::Get()),
128 std::move(addr_or_group_id), preset_index,
129 std::move(preset_name)));
130 }
131
RemoveDevice(const RawAddress & addr)132 void RemoveDevice(const RawAddress& addr) override {
133 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr);
134
135 /* RemoveDevice can be called on devices that don't have BAS enabled */
136 if (HasClient::IsHasClientRunning()) {
137 do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect,
138 Unretained(HasClient::Get()), addr));
139 }
140
141 do_in_jni_thread(FROM_HERE, Bind(&btif_storage_remove_leaudio_has, addr));
142 }
143
Cleanup(void)144 void Cleanup(void) override {
145 DVLOG(2) << __func__;
146 do_in_main_thread(FROM_HERE, Bind(&HasClient::CleanUp));
147 }
148
OnConnectionState(ConnectionState state,const RawAddress & addr)149 void OnConnectionState(ConnectionState state,
150 const RawAddress& addr) override {
151 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr);
152 do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnConnectionState,
153 Unretained(callbacks_), state, addr));
154 }
155
OnDeviceAvailable(const RawAddress & addr,uint8_t features)156 void OnDeviceAvailable(const RawAddress& addr, uint8_t features) override {
157 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr)
158 << " features: " << features;
159
160 do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnDeviceAvailable,
161 Unretained(callbacks_), addr, features));
162 }
163
OnFeaturesUpdate(const RawAddress & addr,uint8_t features)164 void OnFeaturesUpdate(const RawAddress& addr, uint8_t features) override {
165 DVLOG(2) << __func__ << " addr: " << ADDRESS_TO_LOGGABLE_STR(addr)
166 << " ha_features: " << std::bitset<8>(features);
167
168 do_in_jni_thread(FROM_HERE, Bind(&HasClientCallbacks::OnFeaturesUpdate,
169 Unretained(callbacks_), addr, features));
170 }
171
OnActivePresetSelected(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index)172 void OnActivePresetSelected(std::variant<RawAddress, int> addr_or_group_id,
173 uint8_t preset_index) override {
174 DVLOG(2) << __func__ << " preset_index: " << preset_index;
175
176 do_in_jni_thread(FROM_HERE,
177 Bind(&HasClientCallbacks::OnActivePresetSelected,
178 Unretained(callbacks_), std::move(addr_or_group_id),
179 preset_index));
180 }
181
OnActivePresetSelectError(std::variant<RawAddress,int> addr_or_group_id,ErrorCode result_code)182 void OnActivePresetSelectError(std::variant<RawAddress, int> addr_or_group_id,
183 ErrorCode result_code) override {
184 DVLOG(2) << __func__ << " result_code: "
185 << static_cast<std::underlying_type<ErrorCode>::type>(result_code);
186
187 do_in_jni_thread(
188 FROM_HERE,
189 Bind(&HasClientCallbacks::OnActivePresetSelectError,
190 Unretained(callbacks_), std::move(addr_or_group_id), result_code));
191 }
192
OnPresetInfo(std::variant<RawAddress,int> addr_or_group_id,PresetInfoReason change_id,std::vector<PresetInfo> detail_records)193 void OnPresetInfo(std::variant<RawAddress, int> addr_or_group_id,
194 PresetInfoReason change_id,
195 std::vector<PresetInfo> detail_records) override {
196 DVLOG(2) << __func__;
197 for (const auto& rec : detail_records) {
198 DVLOG(2) << "\t index: " << +rec.preset_index << ", change_id: "
199 << (std::underlying_type<PresetInfoReason>::type)change_id
200 << ", writable: " << rec.writable
201 << ", available: " << rec.available
202 << ", name: " << rec.preset_name;
203 }
204
205 do_in_jni_thread(FROM_HERE,
206 Bind(&HasClientCallbacks::OnPresetInfo,
207 Unretained(callbacks_), std::move(addr_or_group_id),
208 change_id, std::move(detail_records)));
209 }
210
OnPresetInfoError(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,ErrorCode result_code)211 void OnPresetInfoError(std::variant<RawAddress, int> addr_or_group_id,
212 uint8_t preset_index, ErrorCode result_code) override {
213 DVLOG(2) << __func__ << " result_code: "
214 << static_cast<std::underlying_type<ErrorCode>::type>(result_code);
215
216 do_in_jni_thread(
217 FROM_HERE,
218 Bind(&HasClientCallbacks::OnPresetInfoError, Unretained(callbacks_),
219 std::move(addr_or_group_id), preset_index, result_code));
220 }
221
OnSetPresetNameError(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,ErrorCode result_code)222 void OnSetPresetNameError(std::variant<RawAddress, int> addr_or_group_id,
223 uint8_t preset_index,
224 ErrorCode result_code) override {
225 DVLOG(2) << __func__ << " result_code: "
226 << static_cast<std::underlying_type<ErrorCode>::type>(result_code);
227
228 do_in_jni_thread(
229 FROM_HERE,
230 Bind(&HasClientCallbacks::OnSetPresetNameError, Unretained(callbacks_),
231 std::move(addr_or_group_id), preset_index, result_code));
232 }
233
234 private:
235 HasClientCallbacks* callbacks_;
236 };
237
238 } /* namespace */
239
btif_has_client_get_interface(void)240 HasClientInterface* btif_has_client_get_interface(void) {
241 if (!has_client_instance)
242 has_client_instance.reset(new HearingAaccessClientServiceInterfaceImpl());
243
244 return has_client_instance.get();
245 }
246