1 /******************************************************************************
2  *
3  *  Copyright 2018 The Android Open Source Project
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 
19 /* Hearing Aid Profile Interface */
20 
21 #include "btif_hearing_aid.h"
22 
23 #include <base/functional/bind.h>
24 #include <base/location.h>
25 #include <hardware/bt_hearing_aid.h>
26 
27 #include <cstdint>
28 #include <memory>
29 #include <utility>
30 
31 #include "bta_hearing_aid_api.h"
32 #include "btif_common.h"
33 #include "btif_profile_storage.h"
34 #include "hardware/avrcp/avrcp.h"
35 #include "stack/include/main_thread.h"
36 #include "types/raw_address.h"
37 
38 using base::Bind;
39 using base::Unretained;
40 using bluetooth::hearing_aid::ConnectionState;
41 using bluetooth::hearing_aid::HearingAidCallbacks;
42 using bluetooth::hearing_aid::HearingAidInterface;
43 
44 // template specialization
45 template <>
jni_thread_wrapper(base::Callback<void ()> cb)46 base::Callback<void()> jni_thread_wrapper(base::Callback<void()> cb) {
47   return base::Bind([](base::Callback<void()> cb) { do_in_jni_thread(cb); }, std::move(cb));
48 }
49 
50 namespace {
51 class HearingAidInterfaceImpl;
52 std::unique_ptr<HearingAidInterface> hearingAidInstance;
53 
54 class HearingAidInterfaceImpl : public bluetooth::hearing_aid::HearingAidInterface,
55                                 public HearingAidCallbacks {
56   ~HearingAidInterfaceImpl() override = default;
57 
Init(HearingAidCallbacks * callbacks)58   void Init(HearingAidCallbacks* callbacks) override {
59     this->callbacks = callbacks;
60     do_in_main_thread(Bind(&HearingAid::Initialize, this,
61                            jni_thread_wrapper(Bind(&btif_storage_load_bonded_hearing_aids))));
62   }
63 
OnConnectionState(ConnectionState state,const RawAddress & address)64   void OnConnectionState(ConnectionState state, const RawAddress& address) override {
65     do_in_jni_thread(
66             Bind(&HearingAidCallbacks::OnConnectionState, Unretained(callbacks), state, address));
67   }
68 
OnDeviceAvailable(uint8_t capabilities,uint64_t hiSyncId,const RawAddress & address)69   void OnDeviceAvailable(uint8_t capabilities, uint64_t hiSyncId,
70                          const RawAddress& address) override {
71     do_in_jni_thread(Bind(&HearingAidCallbacks::OnDeviceAvailable, Unretained(callbacks),
72                           capabilities, hiSyncId, address));
73   }
74 
Connect(const RawAddress & address)75   void Connect(const RawAddress& address) override {
76     do_in_main_thread(Bind(&HearingAid::Connect, address));
77   }
78 
Disconnect(const RawAddress & address)79   void Disconnect(const RawAddress& address) override {
80     do_in_main_thread(Bind(&HearingAid::Disconnect, address));
81     do_in_jni_thread(Bind(&btif_storage_set_hearing_aid_acceptlist, address, false));
82   }
83 
AddToAcceptlist(const RawAddress & address)84   void AddToAcceptlist(const RawAddress& address) override {
85     do_in_main_thread(Bind(&HearingAid::AddToAcceptlist, address));
86     do_in_jni_thread(Bind(&btif_storage_set_hearing_aid_acceptlist, address, true));
87   }
88 
SetVolume(int8_t volume)89   void SetVolume(int8_t volume) override {
90     do_in_main_thread(Bind(&HearingAid::SetVolume, volume));
91   }
92 
RemoveDevice(const RawAddress & address)93   void RemoveDevice(const RawAddress& address) override {
94     // RemoveDevice can be called on devices that don't have HA enabled
95     if (HearingAid::IsHearingAidRunning()) {
96       do_in_main_thread(Bind(&HearingAid::Disconnect, address));
97     }
98 
99     do_in_jni_thread(Bind(&btif_storage_remove_hearing_aid, address));
100   }
101 
Cleanup(void)102   void Cleanup(void) override { do_in_main_thread(Bind(&HearingAid::CleanUp)); }
103 
104 private:
105   HearingAidCallbacks* callbacks;
106 };
107 
108 }  // namespace
109 
btif_hearing_aid_get_interface()110 HearingAidInterface* btif_hearing_aid_get_interface() {
111   if (!hearingAidInstance) {
112     hearingAidInstance.reset(new HearingAidInterfaceImpl());
113   }
114 
115   return hearingAidInstance.get();
116 }
117