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/functional/bind.h>
19 #include <base/location.h>
20 #include <hardware/bluetooth.h>
21 #include <hardware/bt_has.h>
22
23 #include <bitset>
24 #include <string>
25 #include <vector>
26
27 #include "bta_has_api.h"
28 #include "btif_common.h"
29 #include "btif_profile_storage.h"
30 #include "stack/include/main_thread.h"
31
32 using base::Bind;
33 using base::Owned;
34 using base::Passed;
35 using base::Unretained;
36 using bluetooth::has::ConnectionState;
37 using bluetooth::has::ErrorCode;
38 using bluetooth::has::HasClientCallbacks;
39 using bluetooth::has::HasClientInterface;
40 using bluetooth::has::PresetInfo;
41 using bluetooth::has::PresetInfoReason;
42
43 using bluetooth::le_audio::has::HasClient;
44
45 namespace {
46 std::unique_ptr<HasClientInterface> has_client_instance;
47
48 class HearingAaccessClientServiceInterfaceImpl : public HasClientInterface,
49 public HasClientCallbacks {
50 ~HearingAaccessClientServiceInterfaceImpl() override = default;
51
Init(HasClientCallbacks * callbacks)52 void Init(HasClientCallbacks* callbacks) override {
53 this->callbacks_ = callbacks;
54
55 do_in_main_thread(
56 FROM_HERE, Bind(&HasClient::Initialize, this,
57 jni_thread_wrapper(Bind(
58 &btif_storage_load_bonded_leaudio_has_devices))));
59 }
60
Connect(const RawAddress & addr)61 void Connect(const RawAddress& addr) override {
62 do_in_main_thread(FROM_HERE, Bind(&HasClient::Connect,
63 Unretained(HasClient::Get()), addr));
64
65 do_in_jni_thread(
66 Bind(&btif_storage_set_leaudio_has_acceptlist, addr, true));
67 }
68
Disconnect(const RawAddress & addr)69 void Disconnect(const RawAddress& addr) override {
70 do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect,
71 Unretained(HasClient::Get()), addr));
72
73 do_in_jni_thread(
74 Bind(&btif_storage_set_leaudio_has_acceptlist, addr, false));
75 }
76
SelectActivePreset(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index)77 void SelectActivePreset(std::variant<RawAddress, int> addr_or_group_id,
78 uint8_t preset_index) override {
79 do_in_main_thread(
80 FROM_HERE,
81 Bind(&HasClient::SelectActivePreset, Unretained(HasClient::Get()),
82 std::move(addr_or_group_id), preset_index));
83 }
84
NextActivePreset(std::variant<RawAddress,int> addr_or_group_id)85 void NextActivePreset(
86 std::variant<RawAddress, int> addr_or_group_id) override {
87 do_in_main_thread(FROM_HERE, Bind(&HasClient::NextActivePreset,
88 Unretained(HasClient::Get()),
89 std::move(addr_or_group_id)));
90 }
91
PreviousActivePreset(std::variant<RawAddress,int> addr_or_group_id)92 void PreviousActivePreset(
93 std::variant<RawAddress, int> addr_or_group_id) override {
94 do_in_main_thread(FROM_HERE, Bind(&HasClient::PreviousActivePreset,
95 Unretained(HasClient::Get()),
96 std::move(addr_or_group_id)));
97 }
98
GetPresetInfo(const RawAddress & addr,uint8_t preset_index)99 void GetPresetInfo(const RawAddress& addr, uint8_t preset_index) override {
100 do_in_main_thread(
101 FROM_HERE, Bind(&HasClient::GetPresetInfo, Unretained(HasClient::Get()),
102 addr, preset_index));
103 }
104
SetPresetName(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,std::string preset_name)105 void SetPresetName(std::variant<RawAddress, int> addr_or_group_id,
106 uint8_t preset_index, std::string preset_name) override {
107 do_in_main_thread(
108 FROM_HERE, Bind(&HasClient::SetPresetName, Unretained(HasClient::Get()),
109 std::move(addr_or_group_id), preset_index,
110 std::move(preset_name)));
111 }
112
RemoveDevice(const RawAddress & addr)113 void RemoveDevice(const RawAddress& addr) override {
114 /* RemoveDevice can be called on devices that don't have BAS enabled */
115 if (HasClient::IsHasClientRunning()) {
116 do_in_main_thread(FROM_HERE, Bind(&HasClient::Disconnect,
117 Unretained(HasClient::Get()), addr));
118 }
119
120 do_in_jni_thread(Bind(&btif_storage_remove_leaudio_has, addr));
121 }
122
Cleanup(void)123 void Cleanup(void) override {
124 do_in_main_thread(FROM_HERE, Bind(&HasClient::CleanUp));
125 }
126
OnConnectionState(ConnectionState state,const RawAddress & addr)127 void OnConnectionState(ConnectionState state,
128 const RawAddress& addr) override {
129 do_in_jni_thread(Bind(&HasClientCallbacks::OnConnectionState,
130 Unretained(callbacks_), state, addr));
131 }
132
OnDeviceAvailable(const RawAddress & addr,uint8_t features)133 void OnDeviceAvailable(const RawAddress& addr, uint8_t features) override {
134 do_in_jni_thread(Bind(&HasClientCallbacks::OnDeviceAvailable,
135 Unretained(callbacks_), addr, features));
136 }
137
OnFeaturesUpdate(const RawAddress & addr,uint8_t features)138 void OnFeaturesUpdate(const RawAddress& addr, uint8_t features) override {
139 do_in_jni_thread(Bind(&HasClientCallbacks::OnFeaturesUpdate,
140 Unretained(callbacks_), addr, features));
141 }
142
OnActivePresetSelected(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index)143 void OnActivePresetSelected(std::variant<RawAddress, int> addr_or_group_id,
144 uint8_t preset_index) override {
145 do_in_jni_thread(Bind(&HasClientCallbacks::OnActivePresetSelected,
146 Unretained(callbacks_), std::move(addr_or_group_id),
147 preset_index));
148 }
149
OnActivePresetSelectError(std::variant<RawAddress,int> addr_or_group_id,ErrorCode result_code)150 void OnActivePresetSelectError(std::variant<RawAddress, int> addr_or_group_id,
151 ErrorCode result_code) override {
152 do_in_jni_thread(Bind(&HasClientCallbacks::OnActivePresetSelectError,
153 Unretained(callbacks_), std::move(addr_or_group_id),
154 result_code));
155 }
156
OnPresetInfo(std::variant<RawAddress,int> addr_or_group_id,PresetInfoReason change_id,std::vector<PresetInfo> detail_records)157 void OnPresetInfo(std::variant<RawAddress, int> addr_or_group_id,
158 PresetInfoReason change_id,
159 std::vector<PresetInfo> detail_records) override {
160 do_in_jni_thread(Bind(&HasClientCallbacks::OnPresetInfo,
161 Unretained(callbacks_), std::move(addr_or_group_id),
162 change_id, std::move(detail_records)));
163 }
164
OnPresetInfoError(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,ErrorCode result_code)165 void OnPresetInfoError(std::variant<RawAddress, int> addr_or_group_id,
166 uint8_t preset_index, ErrorCode result_code) override {
167 do_in_jni_thread(Bind(&HasClientCallbacks::OnPresetInfoError,
168 Unretained(callbacks_), std::move(addr_or_group_id),
169 preset_index, result_code));
170 }
171
OnSetPresetNameError(std::variant<RawAddress,int> addr_or_group_id,uint8_t preset_index,ErrorCode result_code)172 void OnSetPresetNameError(std::variant<RawAddress, int> addr_or_group_id,
173 uint8_t preset_index,
174 ErrorCode result_code) override {
175 do_in_jni_thread(Bind(&HasClientCallbacks::OnSetPresetNameError,
176 Unretained(callbacks_), std::move(addr_or_group_id),
177 preset_index, result_code));
178 }
179
180 private:
181 HasClientCallbacks* callbacks_;
182 };
183
184 } /* namespace */
185
btif_has_client_get_interface(void)186 HasClientInterface* btif_has_client_get_interface(void) {
187 if (!has_client_instance)
188 has_client_instance.reset(new HearingAaccessClientServiceInterfaceImpl());
189
190 return has_client_instance.get();
191 }
192