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