• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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