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