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