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() = 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