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 "bta_hearing_aid_api.h"
22 #include "btif_common.h"
23 #include "btif_storage.h"
24 #include "stack/include/btu.h"
25 
26 #include <base/bind.h>
27 #include <base/location.h>
28 #include <base/logging.h>
29 #include <hardware/bluetooth.h>
30 #include <hardware/bt_hearing_aid.h>
31 
32 using base::Bind;
33 using base::Unretained;
34 using bluetooth::hearing_aid::ConnectionState;
35 using bluetooth::hearing_aid::HearingAidCallbacks;
36 using bluetooth::hearing_aid::HearingAidInterface;
37 
38 // template specialization
39 template <>
jni_thread_wrapper(const base::Location & from_here,base::Callback<void ()> cb)40 base::Callback<void()> jni_thread_wrapper(const base::Location& from_here,
41                                           base::Callback<void()> cb) {
42   return base::Bind(
43       [](const base::Location& from_here, base::Callback<void()> cb) {
44         do_in_jni_thread(from_here, cb);
45       },
46       from_here, std::move(cb));
47 }
48 
49 namespace {
50 class HearingAidInterfaceImpl;
51 std::unique_ptr<HearingAidInterface> hearingAidInstance;
52 
53 class HearingAidInterfaceImpl
54     : public bluetooth::hearing_aid::HearingAidInterface,
55       public HearingAidCallbacks {
56   ~HearingAidInterfaceImpl() override = default;
57 
Init(HearingAidCallbacks * callbacks)58   void Init(HearingAidCallbacks* callbacks) override {
59     DVLOG(2) << __func__;
60     this->callbacks = callbacks;
61     do_in_main_thread(
62         FROM_HERE,
63         Bind(&HearingAid::Initialize, this,
64              jni_thread_wrapper(FROM_HERE,
65                                 Bind(&btif_storage_load_bonded_hearing_aids))));
66   }
67 
OnConnectionState(ConnectionState state,const RawAddress & address)68   void OnConnectionState(ConnectionState state,
69                          const RawAddress& address) override {
70     DVLOG(2) << __func__ << " address: " << address;
71     do_in_jni_thread(FROM_HERE, Bind(&HearingAidCallbacks::OnConnectionState,
72                                      Unretained(callbacks), state, address));
73   }
74 
OnDeviceAvailable(uint8_t capabilities,uint64_t hiSyncId,const RawAddress & address)75   void OnDeviceAvailable(uint8_t capabilities, uint64_t hiSyncId,
76                          const RawAddress& address) override {
77     DVLOG(2) << __func__ << " address: " << address
78              << ", hiSyncId: " << loghex(hiSyncId)
79              << ", capabilities: " << loghex(capabilities);
80     do_in_jni_thread(FROM_HERE, Bind(&HearingAidCallbacks::OnDeviceAvailable,
81                                      Unretained(callbacks), capabilities,
82                                      hiSyncId, address));
83   }
84 
Connect(const RawAddress & address)85   void Connect(const RawAddress& address) override {
86     DVLOG(2) << __func__ << " address: " << address;
87     do_in_main_thread(FROM_HERE, Bind(&HearingAid::Connect,
88                                       Unretained(HearingAid::Get()), address));
89   }
90 
Disconnect(const RawAddress & address)91   void Disconnect(const RawAddress& address) override {
92     DVLOG(2) << __func__ << " address: " << address;
93     do_in_main_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
94                                       Unretained(HearingAid::Get()), address));
95     do_in_jni_thread(FROM_HERE, Bind(&btif_storage_set_hearing_aid_white_list,
96                                      address, false));
97   }
98 
AddToWhiteList(const RawAddress & address)99   void AddToWhiteList(const RawAddress& address) override {
100     VLOG(2) << __func__ << " address: " << address;
101     do_in_main_thread(FROM_HERE, Bind(&HearingAid::AddToWhiteList,
102                                       Unretained(HearingAid::Get()), address));
103     do_in_jni_thread(FROM_HERE, Bind(&btif_storage_set_hearing_aid_white_list,
104                                      address, true));
105   }
106 
SetVolume(int8_t volume)107   void SetVolume(int8_t volume) override {
108     DVLOG(2) << __func__ << " volume: " << +volume;
109     do_in_main_thread(FROM_HERE, Bind(&HearingAid::SetVolume,
110                                       Unretained(HearingAid::Get()), volume));
111   }
112 
RemoveDevice(const RawAddress & address)113   void RemoveDevice(const RawAddress& address) override {
114     DVLOG(2) << __func__ << " address: " << address;
115 
116     // RemoveDevice can be called on devices that don't have HA enabled
117     if (HearingAid::IsHearingAidRunning()) {
118       do_in_main_thread(FROM_HERE,
119                         Bind(&HearingAid::Disconnect,
120                              Unretained(HearingAid::Get()), address));
121     }
122 
123     do_in_jni_thread(FROM_HERE,
124                      Bind(&btif_storage_remove_hearing_aid, address));
125   }
126 
Cleanup(void)127   void Cleanup(void) override {
128     DVLOG(2) << __func__;
129     do_in_main_thread(FROM_HERE, Bind(&HearingAid::CleanUp));
130   }
131 
132  private:
133   HearingAidCallbacks* callbacks;
134 };
135 
136 }  // namespace
137 
btif_hearing_aid_get_interface()138 HearingAidInterface* btif_hearing_aid_get_interface() {
139   if (!hearingAidInstance)
140     hearingAidInstance.reset(new HearingAidInterfaceImpl());
141 
142   return hearingAidInstance.get();
143 }
144