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 /* Volume Control Interface */
19
20 #include <base/bind.h>
21 #include <base/location.h>
22 #include <base/logging.h>
23 #include <hardware/bluetooth.h>
24 #include <hardware/bt_vc.h>
25
26 #include "bta_vc_api.h"
27 #include "btif_common.h"
28 #include "stack/include/btu.h"
29 #include "types/raw_address.h"
30
31 using base::Bind;
32 using base::Unretained;
33 using bluetooth::vc::ConnectionState;
34 using bluetooth::vc::VolumeControlCallbacks;
35 using bluetooth::vc::VolumeControlInterface;
36
37 namespace {
38 std::unique_ptr<VolumeControlInterface> vc_instance;
39
40 class VolumeControlInterfaceImpl : public VolumeControlInterface,
41 public VolumeControlCallbacks {
42 ~VolumeControlInterfaceImpl() override = default;
43
Init(VolumeControlCallbacks * callbacks)44 void Init(VolumeControlCallbacks* callbacks) override {
45 DVLOG(2) << __func__;
46 this->callbacks_ = callbacks;
47 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::Initialize, this));
48 }
49
OnConnectionState(ConnectionState state,const RawAddress & address)50 void OnConnectionState(ConnectionState state,
51 const RawAddress& address) override {
52 DVLOG(2) << __func__ << " address: " << address;
53 do_in_jni_thread(FROM_HERE, Bind(&VolumeControlCallbacks::OnConnectionState,
54 Unretained(callbacks_), state, address));
55 }
56
OnVolumeStateChanged(const RawAddress & address,uint8_t volume,bool mute,bool isAutonomous)57 void OnVolumeStateChanged(const RawAddress& address, uint8_t volume,
58 bool mute, bool isAutonomous) override {
59 DVLOG(2) << __func__ << " address: " << address << " volume: " << volume
60 << " mute: " << mute << " isAutonomous: " << isAutonomous;
61 do_in_jni_thread(
62 FROM_HERE,
63 Bind(&VolumeControlCallbacks::OnVolumeStateChanged,
64 Unretained(callbacks_), address, volume, mute, isAutonomous));
65 }
66
OnGroupVolumeStateChanged(int group_id,uint8_t volume,bool mute,bool isAutonomous)67 void OnGroupVolumeStateChanged(int group_id, uint8_t volume, bool mute,
68 bool isAutonomous) override {
69 DVLOG(2) << __func__ << " group_id: " << group_id << " volume: " << volume
70 << " mute: " << mute << " isAutonomous: " << isAutonomous;
71 do_in_jni_thread(
72 FROM_HERE,
73 Bind(&VolumeControlCallbacks::OnGroupVolumeStateChanged,
74 Unretained(callbacks_), group_id, volume, mute, isAutonomous));
75 }
76
OnDeviceAvailable(const RawAddress & address,uint8_t num_offset)77 void OnDeviceAvailable(const RawAddress& address,
78 uint8_t num_offset) override {
79 DVLOG(2) << __func__ << " address: " << address;
80 do_in_jni_thread(FROM_HERE,
81 Bind(&VolumeControlCallbacks::OnDeviceAvailable,
82 Unretained(callbacks_), address, num_offset));
83 }
84
85 /* Callbacks for Volume Offset Control Service (VOCS) - Extended Audio Outputs
86 */
87
OnExtAudioOutVolumeOffsetChanged(const RawAddress & address,uint8_t ext_output_id,int16_t offset)88 void OnExtAudioOutVolumeOffsetChanged(const RawAddress& address,
89 uint8_t ext_output_id,
90 int16_t offset) override {
91 DVLOG(2) << __func__ << " address: " << address
92 << "ext_output_id: " << ext_output_id << "offset:" << offset;
93
94 do_in_jni_thread(
95 FROM_HERE,
96 Bind(&VolumeControlCallbacks::OnExtAudioOutVolumeOffsetChanged,
97 Unretained(callbacks_), address, ext_output_id, offset));
98 }
99
OnExtAudioOutLocationChanged(const RawAddress & address,uint8_t ext_output_id,uint32_t location)100 void OnExtAudioOutLocationChanged(const RawAddress& address,
101 uint8_t ext_output_id,
102 uint32_t location) override {
103 DVLOG(2) << __func__ << " address: " << address
104 << "ext_output_id: " << ext_output_id
105 << "location:" << loghex(location);
106
107 do_in_jni_thread(
108 FROM_HERE,
109 Bind(&VolumeControlCallbacks::OnExtAudioOutLocationChanged,
110 Unretained(callbacks_), address, ext_output_id, location));
111 }
112
OnExtAudioOutDescriptionChanged(const RawAddress & address,uint8_t ext_output_id,std::string descr)113 void OnExtAudioOutDescriptionChanged(const RawAddress& address,
114 uint8_t ext_output_id,
115 std::string descr) override {
116 DVLOG(2) << __func__ << " address: " << address
117 << "ext_output_id: " << ext_output_id << "descr:" << descr;
118 do_in_jni_thread(
119 FROM_HERE,
120 Bind(&VolumeControlCallbacks::OnExtAudioOutDescriptionChanged,
121 Unretained(callbacks_), address, ext_output_id, descr));
122 }
123
Connect(const RawAddress & address)124 void Connect(const RawAddress& address) override {
125 DVLOG(2) << __func__ << " address: " << address;
126 do_in_main_thread(FROM_HERE,
127 Bind(&VolumeControl::Connect,
128 Unretained(VolumeControl::Get()), address));
129 }
130
Disconnect(const RawAddress & address)131 void Disconnect(const RawAddress& address) override {
132 DVLOG(2) << __func__ << " address: " << address;
133 do_in_main_thread(FROM_HERE,
134 Bind(&VolumeControl::Disconnect,
135 Unretained(VolumeControl::Get()), address));
136 }
137
SetVolume(std::variant<RawAddress,int> addr_or_group_id,uint8_t volume)138 void SetVolume(std::variant<RawAddress, int> addr_or_group_id,
139 uint8_t volume) override {
140 DVLOG(2) << __func__ << " volume: " << volume;
141 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::SetVolume,
142 Unretained(VolumeControl::Get()),
143 std::move(addr_or_group_id), volume));
144 }
145
Mute(std::variant<RawAddress,int> addr_or_group_id)146 void Mute(std::variant<RawAddress, int> addr_or_group_id) override {
147 DVLOG(2) << __func__;
148 do_in_main_thread(
149 FROM_HERE, Bind(&VolumeControl::Mute, Unretained(VolumeControl::Get()),
150 std::move(addr_or_group_id)));
151 }
152
Unmute(std::variant<RawAddress,int> addr_or_group_id)153 void Unmute(std::variant<RawAddress, int> addr_or_group_id) override {
154 DVLOG(2) << __func__;
155 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::UnMute,
156 Unretained(VolumeControl::Get()),
157 std::move(addr_or_group_id)));
158 }
159
RemoveDevice(const RawAddress & address)160 void RemoveDevice(const RawAddress& address) override {
161 DVLOG(2) << __func__ << " address: " << address;
162
163 /* RemoveDevice can be called on devices that don't have HA enabled */
164 if (VolumeControl::IsVolumeControlRunning()) {
165 do_in_main_thread(FROM_HERE,
166 Bind(&VolumeControl::Disconnect,
167 Unretained(VolumeControl::Get()), address));
168 }
169
170 /* Placeholder: Remove things from storage here */
171 }
172
GetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id)173 void GetExtAudioOutVolumeOffset(const RawAddress& address,
174 uint8_t ext_output_id) override {
175 DVLOG(2) << __func__ << " address: " << address
176 << "ext_output_id:" << ext_output_id;
177 do_in_main_thread(
178 FROM_HERE,
179 Bind(&VolumeControl::GetExtAudioOutVolumeOffset,
180 Unretained(VolumeControl::Get()), address, ext_output_id));
181 }
182
SetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id,int16_t offset_val)183 void SetExtAudioOutVolumeOffset(const RawAddress& address,
184 uint8_t ext_output_id,
185 int16_t offset_val) override {
186 DVLOG(2) << __func__ << " address: " << address
187 << "ext_output_id:" << ext_output_id
188 << "ext_output_id:" << offset_val;
189 do_in_main_thread(FROM_HERE,
190 Bind(&VolumeControl::SetExtAudioOutVolumeOffset,
191 Unretained(VolumeControl::Get()), address,
192 ext_output_id, offset_val));
193 }
194
GetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id)195 void GetExtAudioOutLocation(const RawAddress& address,
196 uint8_t ext_output_id) override {
197 DVLOG(2) << __func__ << " address: " << address
198 << "ext_output_id:" << ext_output_id;
199
200 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::GetExtAudioOutLocation,
201 Unretained(VolumeControl::Get()), address,
202 ext_output_id));
203 }
204
SetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id,uint32_t location)205 void SetExtAudioOutLocation(const RawAddress& address, uint8_t ext_output_id,
206 uint32_t location) override {
207 DVLOG(2) << __func__ << " address: " << address
208 << "ext_output_id:" << ext_output_id
209 << "location:" << loghex(location);
210 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::SetExtAudioOutLocation,
211 Unretained(VolumeControl::Get()), address,
212 ext_output_id, location));
213 }
214
GetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id)215 void GetExtAudioOutDescription(const RawAddress& address,
216 uint8_t ext_output_id) override {
217 DVLOG(2) << __func__ << " address: " << address
218 << "ext_output_id:" << ext_output_id;
219
220 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::GetExtAudioOutDescription,
221 Unretained(VolumeControl::Get()), address,
222 ext_output_id));
223 }
224
SetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id,std::string descr)225 void SetExtAudioOutDescription(const RawAddress& address,
226 uint8_t ext_output_id,
227 std::string descr) override {
228 DVLOG(2) << __func__ << " address: " << address
229 << "ext_output_id:" << ext_output_id << "description:" << descr;
230
231 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::SetExtAudioOutDescription,
232 Unretained(VolumeControl::Get()), address,
233 ext_output_id, descr));
234 }
235
Cleanup(void)236 void Cleanup(void) override {
237 DVLOG(2) << __func__;
238 do_in_main_thread(FROM_HERE, Bind(&VolumeControl::CleanUp));
239 }
240
241 private:
242 VolumeControlCallbacks* callbacks_;
243 };
244
245 } /* namespace */
246
btif_volume_control_get_interface(void)247 VolumeControlInterface* btif_volume_control_get_interface(void) {
248 if (!vc_instance) vc_instance.reset(new VolumeControlInterfaceImpl());
249
250 return vc_instance.get();
251 }
252