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 #include <base/bind.h>
19 #include <base/bind_helpers.h>
20 #include <base/logging.h>
21 #include <base/strings/string_number_conversions.h>
22 #include <hardware/bt_vc.h>
23 
24 #include <string>
25 #include <vector>
26 
27 #include "bta_gatt_api.h"
28 #include "bta_gatt_queue.h"
29 #include "bta_vc_api.h"
30 #include "btif_storage.h"
31 #include "devices.h"
32 
33 using base::Closure;
34 using bluetooth::Uuid;
35 using bluetooth::vc::ConnectionState;
36 using namespace bluetooth::vc::internal;
37 
38 namespace {
39 class VolumeControlImpl;
40 VolumeControlImpl* instance;
41 
42 /**
43  * Overview:
44  *
45  * This is Volume Control Implementation class which realize Volume Control
46  * Profile (VCP)
47  *
48  * Each connected peer device supporting Volume Control Service (VCS) is on the
49  * list of devices (volume_control_devices_).
50  *
51  * Once all the mandatory characteristis for all the services are discovered,
52  * Fluoride calls ON_CONNECTED callback.
53  *
54  * It is assumed that whenever application changes general audio options in this
55  * profile e.g. Volume up/down, mute/unmute etc, profile configures all the
56  * devices which are active Le Audio devices.
57  *
58  *
59  */
60 class VolumeControlImpl : public VolumeControl {
61  public:
62   ~VolumeControlImpl() override = default;
63 
VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks * callbacks)64   VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks* callbacks)
65       : gatt_if_(0), callbacks_(callbacks) {
66     BTA_GATTC_AppRegister(
67         gattc_callback_static,
68         base::Bind([](uint8_t client_id, uint8_t status) {
69           if (status != GATT_SUCCESS) {
70             LOG(ERROR) << "Can't start Volume Control profile - no gatt "
71                           "clients left!";
72             return;
73           }
74           instance->gatt_if_ = client_id;
75         }),
76         true);
77   }
78 
Connect(const RawAddress & address)79   void Connect(const RawAddress& address) override {
80     LOG(INFO) << __func__ << " " << address;
81 
82     auto device = volume_control_devices_.FindByAddress(address);
83     if (!device) {
84       volume_control_devices_.Add(address, true);
85     } else {
86       device->connecting_actively = true;
87     }
88 
89     BTA_GATTC_Open(gatt_if_, address, true, false);
90   }
91 
AddFromStorage(const RawAddress & address,bool auto_connect)92   void AddFromStorage(const RawAddress& address, bool auto_connect) {
93     LOG(INFO) << __func__ << " " << address
94               << ", auto_connect=" << auto_connect;
95 
96     if (auto_connect) {
97       volume_control_devices_.Add(address, false);
98 
99       /* Add device into BG connection to accept remote initiated connection */
100       BTA_GATTC_Open(gatt_if_, address, false, false);
101     }
102   }
103 
OnGattConnected(tGATT_STATUS status,uint16_t connection_id,tGATT_IF,RawAddress address,tBT_TRANSPORT,uint16_t)104   void OnGattConnected(tGATT_STATUS status, uint16_t connection_id,
105                        tGATT_IF /*client_if*/, RawAddress address,
106                        tBT_TRANSPORT /*transport*/, uint16_t /*mtu*/) {
107     LOG(INFO) << __func__ << ": address=" << address
108               << ", connection_id=" << connection_id;
109 
110     VolumeControlDevice* device =
111         volume_control_devices_.FindByAddress(address);
112     if (!device) {
113       LOG(ERROR) << __func__ << "Skipping unknown device, address=" << address;
114       return;
115     }
116 
117     if (status != GATT_SUCCESS) {
118       LOG(INFO) << "Failed to connect to Volume Control device";
119       device_cleanup_helper(device, device->connecting_actively);
120       return;
121     }
122 
123     device->connection_id = connection_id;
124 
125     if (device->IsEncryptionEnabled()) {
126       OnEncryptionComplete(address, BTM_SUCCESS);
127       return;
128     }
129 
130     if (!device->EnableEncryption(enc_callback_static)) {
131       device_cleanup_helper(device, device->connecting_actively);
132     }
133   }
134 
OnEncryptionComplete(const RawAddress & address,uint8_t success)135   void OnEncryptionComplete(const RawAddress& address, uint8_t success) {
136     VolumeControlDevice* device =
137         volume_control_devices_.FindByAddress(address);
138     if (!device) {
139       LOG(ERROR) << __func__ << "Skipping unknown device" << address;
140       return;
141     }
142 
143     if (success != BTM_SUCCESS) {
144       LOG(ERROR) << "encryption failed "
145                  << "status: " << int{success};
146       // If the encryption failed, do not remove the device.
147       // Disconnect only, since the Android will try to re-enable encryption
148       // after disconnection
149       device->Disconnect(gatt_if_);
150       if (device->connecting_actively)
151         callbacks_->OnConnectionState(ConnectionState::DISCONNECTED,
152                                       device->address);
153       return;
154     }
155 
156     LOG(INFO) << __func__ << " " << address << "status: " << success;
157 
158     if (device->HasHandles()) {
159       device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static,
160                                      OnGattWriteCccStatic);
161 
162     } else {
163       device->first_connection = true;
164       BTA_GATTC_ServiceSearchRequest(device->connection_id,
165                                      &kVolumeControlUuid);
166     }
167   }
168 
OnServiceChangeEvent(const RawAddress & address)169   void OnServiceChangeEvent(const RawAddress& address) {
170     VolumeControlDevice* device =
171         volume_control_devices_.FindByAddress(address);
172     if (!device) {
173       LOG(ERROR) << __func__ << "Skipping unknown device" << address;
174       return;
175     }
176     LOG(INFO) << __func__ << ": address=" << address;
177     device->first_connection = true;
178     device->service_changed_rcvd = true;
179     BtaGattQueue::Clean(device->connection_id);
180   }
181 
OnServiceDiscDoneEvent(const RawAddress & address)182   void OnServiceDiscDoneEvent(const RawAddress& address) {
183     VolumeControlDevice* device =
184         volume_control_devices_.FindByAddress(address);
185     if (!device) {
186       LOG(ERROR) << __func__ << "Skipping unknown device" << address;
187       return;
188     }
189 
190     if (device->service_changed_rcvd)
191       BTA_GATTC_ServiceSearchRequest(device->connection_id,
192                                      &kVolumeControlUuid);
193   }
194 
OnServiceSearchComplete(uint16_t connection_id,tGATT_STATUS status)195   void OnServiceSearchComplete(uint16_t connection_id, tGATT_STATUS status) {
196     VolumeControlDevice* device =
197         volume_control_devices_.FindByConnId(connection_id);
198     if (!device) {
199       LOG(ERROR) << __func__ << "Skipping unknown device, connection_id="
200                  << loghex(connection_id);
201       return;
202     }
203 
204     /* Known device, nothing to do */
205     if (!device->first_connection) return;
206 
207     if (status != GATT_SUCCESS) {
208       /* close connection and report service discovery complete with error */
209       LOG(ERROR) << "Service discovery failed";
210       device_cleanup_helper(device, device->first_connection);
211       return;
212     }
213 
214     bool success = device->UpdateHandles();
215     if (!success) {
216       LOG(ERROR) << "Incomplete service database";
217       device_cleanup_helper(device, true);
218       return;
219     }
220 
221     device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static,
222                                    OnGattWriteCccStatic);
223   }
224 
OnCharacteristicValueChanged(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void *)225   void OnCharacteristicValueChanged(uint16_t conn_id, tGATT_STATUS status,
226                                     uint16_t handle, uint16_t len,
227                                     uint8_t* value, void* /* data */) {
228     VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id);
229     if (!device) {
230       LOG(INFO) << __func__ << ": unknown conn_id=" << loghex(conn_id);
231       return;
232     }
233 
234     if (status != GATT_SUCCESS) {
235       LOG(INFO) << __func__ << ": status=" << static_cast<int>(status);
236       return;
237     }
238 
239     if (handle == device->volume_state_handle) {
240       OnVolumeControlStateChanged(device, len, value);
241       verify_device_ready(device, handle);
242       return;
243     }
244     if (handle == device->volume_flags_handle) {
245       OnVolumeControlFlagsChanged(device, len, value);
246       verify_device_ready(device, handle);
247       return;
248     }
249 
250     LOG(ERROR) << __func__ << ": unknown handle=" << loghex(handle);
251   }
252 
OnNotificationEvent(uint16_t conn_id,uint16_t handle,uint16_t len,uint8_t * value)253   void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len,
254                            uint8_t* value) {
255     LOG(INFO) << __func__ << ": handle=" << loghex(handle);
256     OnCharacteristicValueChanged(conn_id, GATT_SUCCESS, handle, len, value,
257                                  nullptr);
258   }
259 
VolumeControlReadCommon(uint16_t conn_id,uint16_t handle)260   void VolumeControlReadCommon(uint16_t conn_id, uint16_t handle) {
261     BtaGattQueue::ReadCharacteristic(conn_id, handle, chrc_read_callback_static,
262                                      nullptr);
263   }
264 
OnVolumeControlStateChanged(VolumeControlDevice * device,uint16_t len,uint8_t * value)265   void OnVolumeControlStateChanged(VolumeControlDevice* device, uint16_t len,
266                                    uint8_t* value) {
267     if (len != 3) {
268       LOG(INFO) << __func__ << ": malformed len=" << loghex(len);
269       return;
270     }
271 
272     uint8_t* pp = value;
273     STREAM_TO_UINT8(device->volume, pp);
274     STREAM_TO_UINT8(device->mute, pp);
275     STREAM_TO_UINT8(device->change_counter, pp);
276 
277     LOG(INFO) << __func__ << " " << base::HexEncode(value, len);
278     LOG(INFO) << __func__ << "volume " << loghex(device->volume) << "mute"
279               << loghex(device->mute) << "change_counter"
280               << loghex(device->change_counter);
281 
282     if (!device->device_ready) return;
283 
284     callbacks_->OnVolumeStateChanged(device->address, device->volume,
285                                      device->mute);
286   }
287 
OnVolumeControlFlagsChanged(VolumeControlDevice * device,uint16_t len,uint8_t * value)288   void OnVolumeControlFlagsChanged(VolumeControlDevice* device, uint16_t len,
289                                    uint8_t* value) {
290     device->flags = *value;
291 
292     LOG(INFO) << __func__ << " " << base::HexEncode(value, len);
293     LOG(INFO) << __func__ << "flags " << loghex(device->flags);
294   }
295 
OnGattWriteCcc(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,void *)296   void OnGattWriteCcc(uint16_t connection_id, tGATT_STATUS status,
297                       uint16_t handle, void* /*data*/) {
298     VolumeControlDevice* device =
299         volume_control_devices_.FindByConnId(connection_id);
300     if (!device) {
301       LOG(INFO) << __func__
302                 << "unknown connection_id=" << loghex(connection_id);
303       BtaGattQueue::Clean(connection_id);
304       return;
305     }
306 
307     if (status != GATT_SUCCESS) {
308       LOG(ERROR) << __func__
309                  << "Failed to register for notification: " << loghex(handle)
310                  << " status: " << status;
311       device_cleanup_helper(device, true);
312       return;
313     }
314 
315     LOG(INFO) << __func__
316               << "Successfully register for indications: " << loghex(handle);
317 
318     verify_device_ready(device, handle);
319   }
320 
OnGattWriteCccStatic(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,void * data)321   static void OnGattWriteCccStatic(uint16_t connection_id, tGATT_STATUS status,
322                                    uint16_t handle, void* data) {
323     if (!instance) {
324       LOG(ERROR) << __func__ << "No instance=" << handle;
325       return;
326     }
327 
328     instance->OnGattWriteCcc(connection_id, status, handle, data);
329   }
330 
Dump(int fd)331   void Dump(int fd) { volume_control_devices_.DebugDump(fd); }
332 
Disconnect(const RawAddress & address)333   void Disconnect(const RawAddress& address) override {
334     VolumeControlDevice* device =
335         volume_control_devices_.FindByAddress(address);
336     if (!device) {
337       LOG(INFO) << "Device not connected to profile" << address;
338       return;
339     }
340 
341     LOG(INFO) << __func__ << ": " << address;
342     LOG(INFO) << "GAP_EVT_CONN_CLOSED: " << device->address;
343     device_cleanup_helper(device, true);
344   }
345 
OnGattDisconnected(uint16_t connection_id,tGATT_IF,RawAddress remote_bda,tGATT_DISCONN_REASON)346   void OnGattDisconnected(uint16_t connection_id, tGATT_IF /*client_if*/,
347                           RawAddress remote_bda,
348                           tGATT_DISCONN_REASON /*reason*/) {
349     VolumeControlDevice* device =
350         volume_control_devices_.FindByConnId(connection_id);
351     if (!device) {
352       LOG(ERROR) << __func__
353                  << " Skipping unknown device disconnect, connection_id="
354                  << loghex(connection_id);
355       return;
356     }
357 
358     // If we get here, it means, device has not been exlicitly disconnected.
359     bool device_ready = device->device_ready;
360 
361     device_cleanup_helper(device, device->connecting_actively);
362 
363     if (device_ready) {
364       volume_control_devices_.Add(remote_bda, true);
365 
366       /* Add device into BG connection to accept remote initiated connection */
367       BTA_GATTC_Open(gatt_if_, remote_bda, false, false);
368     }
369   }
370 
OnWriteControlResponse(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,void *)371   void OnWriteControlResponse(uint16_t connection_id, tGATT_STATUS status,
372                               uint16_t handle, void* /*data*/) {
373     VolumeControlDevice* device =
374         volume_control_devices_.FindByConnId(connection_id);
375     if (!device) {
376       LOG(ERROR) << __func__
377                  << "Skipping unknown device disconnect, connection_id="
378                  << loghex(connection_id);
379       return;
380     }
381 
382     LOG(INFO) << "Write response handle: " << loghex(handle)
383               << " status: " << loghex((int)(status));
384   }
385 
SetVolume(std::variant<RawAddress,int> addr_or_group_id,uint8_t volume)386   void SetVolume(std::variant<RawAddress, int> addr_or_group_id,
387                  uint8_t volume) override {
388     LOG(INFO) << __func__ << "vol: " << +volume;
389 
390     if (std::holds_alternative<RawAddress>(addr_or_group_id)) {
391       std::vector<RawAddress> devices = {
392           std::get<RawAddress>(addr_or_group_id)};
393       std::vector<uint8_t> arg({volume});
394       devices_control_point_helper(devices,
395                                    kControlPointOpcodeSetAbsoluteVolume, &arg);
396       return;
397     }
398 
399     /* TODO implement handling group request */
400   }
401 
CleanUp()402   void CleanUp() {
403     LOG(INFO) << __func__;
404     volume_control_devices_.Disconnect(gatt_if_);
405     volume_control_devices_.Clear();
406     BTA_GATTC_AppDeregister(gatt_if_);
407   }
408 
409  private:
410   tGATT_IF gatt_if_;
411   bluetooth::vc::VolumeControlCallbacks* callbacks_;
412   VolumeControlDevices volume_control_devices_;
413 
verify_device_ready(VolumeControlDevice * device,uint16_t handle)414   void verify_device_ready(VolumeControlDevice* device, uint16_t handle) {
415     if (device->device_ready) return;
416 
417     // VerifyReady sets the device_ready flag if all remaining GATT operations
418     // are completed
419     if (device->VerifyReady(handle)) {
420       LOG(INFO) << __func__ << "Outstanding reads completed ";
421 
422       callbacks_->OnConnectionState(ConnectionState::CONNECTED,
423                                     device->address);
424 
425       device->connecting_actively = true;
426 
427       device->first_connection = false;
428 
429       // once profile connected we can notify current states
430       callbacks_->OnVolumeStateChanged(device->address, device->volume,
431                                        device->mute);
432 
433       device->EnqueueRemainingRequests(gatt_if_, chrc_read_callback_static,
434                                        OnGattWriteCccStatic);
435     }
436   }
437 
device_cleanup_helper(VolumeControlDevice * device,bool notify)438   void device_cleanup_helper(VolumeControlDevice* device, bool notify) {
439     device->Disconnect(gatt_if_);
440     if (notify)
441       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED,
442                                     device->address);
443     volume_control_devices_.Remove(device->address);
444   }
445 
devices_control_point_helper(std::vector<RawAddress> & devices,uint8_t opcode,const std::vector<uint8_t> * arg)446   void devices_control_point_helper(std::vector<RawAddress>& devices,
447                                     uint8_t opcode,
448                                     const std::vector<uint8_t>* arg) {
449     volume_control_devices_.ControlPointOperation(
450         devices, opcode, arg,
451         [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle,
452            void* data) {
453           if (instance)
454             instance->OnWriteControlResponse(connection_id, status, handle,
455                                              data);
456         },
457         nullptr);
458   }
459 
gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)460   void gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
461     LOG(INFO) << __func__ << " event = " << static_cast<int>(event);
462 
463     if (p_data == nullptr) return;
464 
465     switch (event) {
466       case BTA_GATTC_OPEN_EVT: {
467         tBTA_GATTC_OPEN& o = p_data->open;
468         OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda,
469                         o.transport, o.mtu);
470 
471       } break;
472 
473       case BTA_GATTC_CLOSE_EVT: {
474         tBTA_GATTC_CLOSE& c = p_data->close;
475         OnGattDisconnected(c.conn_id, c.client_if, c.remote_bda, c.reason);
476       } break;
477 
478       case BTA_GATTC_SEARCH_CMPL_EVT:
479         OnServiceSearchComplete(p_data->search_cmpl.conn_id,
480                                 p_data->search_cmpl.status);
481         break;
482 
483       case BTA_GATTC_NOTIF_EVT: {
484         tBTA_GATTC_NOTIFY& n = p_data->notify;
485         if (!n.is_notify || n.len > GATT_MAX_ATTR_LEN) {
486           LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify="
487                      << n.is_notify << ", len=" << static_cast<int>(n.len);
488           break;
489         }
490         OnNotificationEvent(n.conn_id, n.handle, n.len, n.value);
491       } break;
492 
493       case BTA_GATTC_ENC_CMPL_CB_EVT:
494         OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true);
495         break;
496 
497       case BTA_GATTC_SRVC_CHG_EVT:
498         OnServiceChangeEvent(p_data->remote_bda);
499         break;
500 
501       case BTA_GATTC_SRVC_DISC_DONE_EVT:
502         OnServiceDiscDoneEvent(p_data->remote_bda);
503         break;
504 
505       default:
506         break;
507     }
508   }
509 
gattc_callback_static(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)510   static void gattc_callback_static(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
511     if (instance) instance->gattc_callback(event, p_data);
512   }
513 
enc_callback_static(const RawAddress * address,tBT_TRANSPORT,void *,tBTM_STATUS status)514   static void enc_callback_static(const RawAddress* address, tBT_TRANSPORT,
515                                   void*, tBTM_STATUS status) {
516     if (instance) instance->OnEncryptionComplete(*address, status);
517   }
518 
chrc_read_callback_static(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)519   static void chrc_read_callback_static(uint16_t conn_id, tGATT_STATUS status,
520                                         uint16_t handle, uint16_t len,
521                                         uint8_t* value, void* data) {
522     if (instance)
523       instance->OnCharacteristicValueChanged(conn_id, status, handle, len,
524                                              value, data);
525   }
526 };
527 }  // namespace
528 
Initialize(bluetooth::vc::VolumeControlCallbacks * callbacks)529 void VolumeControl::Initialize(
530     bluetooth::vc::VolumeControlCallbacks* callbacks) {
531   if (instance) {
532     LOG(ERROR) << "Already initialized!";
533     return;
534   }
535 
536   instance = new VolumeControlImpl(callbacks);
537 }
538 
IsVolumeControlRunning()539 bool VolumeControl::IsVolumeControlRunning() { return instance; }
540 
Get(void)541 VolumeControl* VolumeControl::Get(void) {
542   CHECK(instance);
543   return instance;
544 };
545 
AddFromStorage(const RawAddress & address,bool auto_connect)546 void VolumeControl::AddFromStorage(const RawAddress& address,
547                                    bool auto_connect) {
548   if (!instance) {
549     LOG(ERROR) << "Not initialized yet";
550     return;
551   }
552 
553   instance->AddFromStorage(address, auto_connect);
554 };
555 
CleanUp()556 void VolumeControl::CleanUp() {
557   if (!instance) {
558     LOG(ERROR) << "not initialized!";
559     return;
560   }
561 
562   VolumeControlImpl* ptr = instance;
563   instance = nullptr;
564 
565   ptr->CleanUp();
566 
567   delete ptr;
568 };
569 
DebugDump(int fd)570 void VolumeControl::DebugDump(int fd) {
571   dprintf(fd, "Volume Control Manager:\n");
572   if (instance) instance->Dump(fd);
573   dprintf(fd, "\n");
574 }
575