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/functional/bind.h>
19 #include <base/strings/string_number_conversions.h>
20 #include <base/strings/string_util.h>
21 #include <bluetooth/log.h>
22 #include <hardware/bt_gatt_types.h>
23 #include <hardware/bt_vc.h>
24 
25 #include <mutex>
26 #include <string>
27 #include <vector>
28 
29 #include "bta/le_audio/le_audio_types.h"
30 #include "bta_csis_api.h"
31 #include "bta_gatt_api.h"
32 #include "bta_gatt_queue.h"
33 #include "bta_vc_api.h"
34 #include "devices.h"
35 #include "internal_include/bt_trace.h"
36 #include "os/log.h"
37 #include "osi/include/osi.h"
38 #include "stack/btm/btm_sec.h"
39 #include "stack/include/bt_types.h"
40 #include "types/bluetooth/uuid.h"
41 #include "types/raw_address.h"
42 
43 using base::Closure;
44 using bluetooth::Uuid;
45 using bluetooth::csis::CsisClient;
46 using bluetooth::vc::ConnectionState;
47 using namespace bluetooth::vc::internal;
48 using namespace bluetooth;
49 
50 namespace {
51 class VolumeControlImpl;
52 VolumeControlImpl* instance;
53 std::mutex instance_mutex;
54 
55 /**
56  * Overview:
57  *
58  * This is Volume Control Implementation class which realize Volume Control
59  * Profile (VCP)
60  *
61  * Each connected peer device supporting Volume Control Service (VCS) is on the
62  * list of devices (volume_control_devices_). When VCS is discovered on the peer
63  * device, Android does search for all the instances Volume Offset Service
64  * (VOCS). Note that AIS and VOCS are optional.
65  *
66  * Once all the mandatory characteristis for all the services are discovered,
67  * Fluoride calls ON_CONNECTED callback.
68  *
69  * It is assumed that whenever application changes general audio options in this
70  * profile e.g. Volume up/down, mute/unmute etc, profile configures all the
71  * devices which are active Le Audio devices.
72  *
73  * Peer devices has at maximum one instance of VCS and 0 or more instance of
74  * VOCS. Android gets access to External Audio Outputs using appropriate ID.
75  * Also each of the External Device has description
76  * characteristic and Type which gives the application hint what it is a device.
77  * Examples of such devices:
78  *   External Output: 1 instance to controller ballance between set of devices
79  *   External Output: each of 5.1 speaker set etc.
80  */
81 class VolumeControlImpl : public VolumeControl {
82  public:
83   ~VolumeControlImpl() override = default;
84 
VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks * callbacks,const base::Closure & initCb)85   VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks* callbacks,
86                     const base::Closure& initCb)
87       : gatt_if_(0), callbacks_(callbacks), latest_operation_id_(0) {
88     BTA_GATTC_AppRegister(
89         gattc_callback_static,
90         base::Bind(
91             [](const base::Closure& initCb, uint8_t client_id, uint8_t status) {
92               if (status != GATT_SUCCESS) {
93                 log::error(
94                     "Can't start Volume Control profile - no gatt clients "
95                     "left!");
96                 return;
97               }
98               instance->gatt_if_ = client_id;
99               initCb.Run();
100             },
101             initCb),
102         true);
103   }
104 
StartOpportunisticConnect(const RawAddress & address)105   void StartOpportunisticConnect(const RawAddress& address) {
106     /* Oportunistic works only for direct connect,
107      * but in fact this is background connect
108      */
109     log::info(": {}", address);
110     BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, true);
111   }
112 
Connect(const RawAddress & address)113   void Connect(const RawAddress& address) override {
114     log::info(": {}", address);
115 
116     auto device = volume_control_devices_.FindByAddress(address);
117     if (!device) {
118       if (!BTM_IsLinkKeyKnown(address, BT_TRANSPORT_LE)) {
119         log::error("Connecting  {} when not bonded", address);
120         callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
121         return;
122       }
123       volume_control_devices_.Add(address, true);
124     } else {
125       device->connecting_actively = true;
126 
127       if (device->IsConnected()) {
128         log::warn("address={}, connection_id={} already connected.", address,
129                   device->connection_id);
130 
131         if (device->IsReady()) {
132           callbacks_->OnConnectionState(ConnectionState::CONNECTED,
133                                         device->address);
134         } else {
135           OnGattConnected(GATT_SUCCESS, device->connection_id, gatt_if_,
136                           device->address, BT_TRANSPORT_LE, GATT_MAX_MTU_SIZE);
137         }
138         return;
139       }
140     }
141 
142     StartOpportunisticConnect(address);
143   }
144 
AddFromStorage(const RawAddress & address)145   void AddFromStorage(const RawAddress& address) {
146     log::info("{}", address);
147     volume_control_devices_.Add(address, false);
148     StartOpportunisticConnect(address);
149   }
150 
OnGattConnected(tGATT_STATUS status,uint16_t connection_id,tGATT_IF,RawAddress address,tBT_TRANSPORT transport,uint16_t)151   void OnGattConnected(tGATT_STATUS status, uint16_t connection_id,
152                        tGATT_IF /*client_if*/, RawAddress address,
153                        tBT_TRANSPORT transport, uint16_t /*mtu*/) {
154     log::info("{}, conn_id=0x{:04x}, transport={}, status={}(0x{:02x})",
155               address, connection_id, bt_transport_text(transport),
156               gatt_status_text(status), status);
157 
158     if (transport != BT_TRANSPORT_LE) {
159       log::warn("Only LE connection is allowed (transport {})",
160                 bt_transport_text(transport));
161       BTA_GATTC_Close(connection_id);
162       return;
163     }
164 
165     VolumeControlDevice* device =
166         volume_control_devices_.FindByAddress(address);
167     if (!device) {
168       log::error("Skipping unknown device, address={}", address);
169       return;
170     }
171 
172     if (status != GATT_SUCCESS) {
173       log::info("Failed to connect to Volume Control device");
174       device_cleanup_helper(device, device->connecting_actively);
175       return;
176     }
177 
178     device->connection_id = connection_id;
179 
180     /* Make sure to remove device from background connect.
181      * It will be added back if needed, when device got disconnected
182      */
183     BTA_GATTC_CancelOpen(gatt_if_, address, false);
184 
185     if (device->IsEncryptionEnabled()) {
186       OnEncryptionComplete(address, BTM_SUCCESS);
187       return;
188     }
189 
190     if (!device->EnableEncryption()) {
191       log::error("Link key is not known for {}, disconnect profile", address);
192       device->Disconnect(gatt_if_);
193     }
194   }
195 
OnEncryptionComplete(const RawAddress & address,uint8_t success)196   void OnEncryptionComplete(const RawAddress& address, uint8_t success) {
197     VolumeControlDevice* device =
198         volume_control_devices_.FindByAddress(address);
199     if (!device) {
200       log::error("Skipping unknown device {}", address);
201       return;
202     }
203 
204     if (success != BTM_SUCCESS) {
205       log::error("encryption failed status: {}", int{success});
206       // If the encryption failed, do not remove the device.
207       // Disconnect only, since the Android will try to re-enable encryption
208       // after disconnection
209       device_cleanup_helper(device, device->connecting_actively);
210       return;
211     }
212 
213     log::info("{} status: {}", address, success);
214 
215     if (device->HasHandles()) {
216       device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static,
217                                      OnGattWriteCccStatic);
218 
219     } else {
220       BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
221     }
222   }
223 
ClearDeviceInformationAndStartSearch(VolumeControlDevice * device)224   void ClearDeviceInformationAndStartSearch(VolumeControlDevice* device) {
225     if (!device) {
226       log::error("Device is null");
227       return;
228     }
229 
230     log::info("address={}", device->address);
231     if (device->known_service_handles_ == false) {
232       log::info("Device already is waiting for new services");
233       return;
234     }
235 
236     std::vector<RawAddress> devices = {device->address};
237     device->DeregisterNotifications(gatt_if_);
238 
239     RemovePendingVolumeControlOperations(devices,
240                                          bluetooth::groups::kGroupUnknown);
241     device->ResetHandles();
242     BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
243   }
244 
OnServiceChangeEvent(const RawAddress & address)245   void OnServiceChangeEvent(const RawAddress& address) {
246     VolumeControlDevice* device =
247         volume_control_devices_.FindByAddress(address);
248     if (!device) {
249       log::error("Skipping unknown device {}", address);
250       return;
251     }
252 
253     ClearDeviceInformationAndStartSearch(device);
254   }
255 
OnServiceDiscDoneEvent(const RawAddress & address)256   void OnServiceDiscDoneEvent(const RawAddress& address) {
257     VolumeControlDevice* device =
258         volume_control_devices_.FindByAddress(address);
259     if (!device) {
260       log::error("Skipping unknown device {}", address);
261       return;
262     }
263 
264     if (device->known_service_handles_ == false) {
265       BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
266     }
267   }
268 
OnServiceSearchComplete(uint16_t connection_id,tGATT_STATUS status)269   void OnServiceSearchComplete(uint16_t connection_id, tGATT_STATUS status) {
270     VolumeControlDevice* device =
271         volume_control_devices_.FindByConnId(connection_id);
272     if (!device) {
273       log::error("Skipping unknown device, connection_id=0x{:x}",
274                  connection_id);
275       return;
276     }
277 
278     /* Known device, nothing to do */
279     if (device->IsReady()) return;
280 
281     if (status != GATT_SUCCESS) {
282       /* close connection and report service discovery complete with error */
283       log::error("Service discovery failed");
284       device_cleanup_helper(device, device->connecting_actively);
285       return;
286     }
287 
288     if (!device->IsEncryptionEnabled()) {
289       log::warn("Device not yet bonded - waiting for encryption");
290       return;
291     }
292 
293     bool success = device->UpdateHandles();
294     if (!success) {
295       log::error("Incomplete service database");
296       device_cleanup_helper(device, device->connecting_actively);
297       return;
298     }
299 
300     device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static,
301                                    OnGattWriteCccStatic);
302   }
303 
OnCharacteristicValueChanged(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data,bool is_notification)304   void OnCharacteristicValueChanged(uint16_t conn_id, tGATT_STATUS status,
305                                     uint16_t handle, uint16_t len,
306                                     uint8_t* value, void* data,
307                                     bool is_notification) {
308     VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id);
309     if (!device) {
310       log::info("unknown conn_id=0x{:x}", conn_id);
311       return;
312     }
313 
314     if (status != GATT_SUCCESS) {
315       log::info("status=0x{:02x}", static_cast<int>(status));
316       if (status == GATT_DATABASE_OUT_OF_SYNC) {
317         log::info("Database out of sync for {}", device->address);
318         ClearDeviceInformationAndStartSearch(device);
319       }
320       return;
321     }
322 
323     if (handle == device->volume_state_handle) {
324       OnVolumeControlStateReadOrNotified(device, len, value, is_notification);
325       verify_device_ready(device, handle);
326       return;
327     }
328     if (handle == device->volume_flags_handle) {
329       OnVolumeControlFlagsChanged(device, len, value);
330       verify_device_ready(device, handle);
331       return;
332     }
333 
334     const gatt::Service* service = BTA_GATTC_GetOwningService(conn_id, handle);
335     if (service == nullptr) return;
336 
337     VolumeOffset* offset =
338         device->audio_offsets.FindByServiceHandle(service->handle);
339     if (offset != nullptr) {
340       if (handle == offset->state_handle) {
341         OnExtAudioOutStateChanged(device, offset, len, value);
342       } else if (handle == offset->audio_location_handle) {
343         OnExtAudioOutLocationChanged(device, offset, len, value);
344       } else if (handle == offset->audio_descr_handle) {
345         OnOffsetOutputDescChanged(device, offset, len, value);
346       } else {
347         log::error("unknown offset handle=0x{:x}", handle);
348         return;
349       }
350 
351       verify_device_ready(device, handle);
352       return;
353     }
354 
355     log::error("unknown handle=0x{:x}", handle);
356   }
357 
OnNotificationEvent(uint16_t conn_id,uint16_t handle,uint16_t len,uint8_t * value)358   void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len,
359                            uint8_t* value) {
360     log::info("handle=0x{:x}", handle);
361     OnCharacteristicValueChanged(conn_id, GATT_SUCCESS, handle, len, value,
362                                  nullptr, true);
363   }
364 
VolumeControlReadCommon(uint16_t conn_id,uint16_t handle)365   void VolumeControlReadCommon(uint16_t conn_id, uint16_t handle) {
366     BtaGattQueue::ReadCharacteristic(conn_id, handle, chrc_read_callback_static,
367                                      nullptr);
368   }
369 
HandleAutonomusVolumeChange(VolumeControlDevice * device,bool is_volume_change,bool is_mute_change)370   void HandleAutonomusVolumeChange(VolumeControlDevice* device,
371                                    bool is_volume_change, bool is_mute_change) {
372     log::debug("{}, is volume change: {}, is mute change: {}", device->address,
373                is_volume_change, is_mute_change);
374 
375     if (!is_volume_change && !is_mute_change) {
376       log::error("Autonomous change but volume and mute did not changed.");
377       return;
378     }
379 
380     auto csis_api = CsisClient::Get();
381     if (!csis_api) {
382       log::warn("Csis module is not available");
383       callbacks_->OnVolumeStateChanged(device->address, device->volume,
384                                        device->mute, true);
385       return;
386     }
387 
388     auto group_id =
389         csis_api->GetGroupId(device->address, le_audio::uuid::kCapServiceUuid);
390     if (group_id == bluetooth::groups::kGroupUnknown) {
391       log::warn("No group for device {}", device->address);
392       callbacks_->OnVolumeStateChanged(device->address, device->volume,
393                                        device->mute, true);
394       return;
395     }
396 
397     auto devices = csis_api->GetDeviceList(group_id);
398     for (auto it = devices.begin(); it != devices.end();) {
399       auto dev = volume_control_devices_.FindByAddress(*it);
400       if (!dev || !dev->IsConnected() || (dev->address == device->address)) {
401         it = devices.erase(it);
402       } else {
403         it++;
404       }
405     }
406 
407     if (devices.empty() && (is_volume_change || is_mute_change)) {
408       log::info("No more devices in the group right now");
409       callbacks_->OnGroupVolumeStateChanged(group_id, device->volume,
410                                             device->mute, true);
411       return;
412     }
413 
414     if (is_volume_change) {
415       std::vector<uint8_t> arg({device->volume});
416       PrepareVolumeControlOperation(devices, group_id, true,
417                                     kControlPointOpcodeSetAbsoluteVolume, arg);
418     }
419 
420     if (is_mute_change) {
421       std::vector<uint8_t> arg;
422       uint8_t opcode =
423           device->mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute;
424       PrepareVolumeControlOperation(devices, group_id, true, opcode, arg);
425     }
426 
427     StartQueueOperation();
428   }
429 
OnVolumeControlStateReadOrNotified(VolumeControlDevice * device,uint16_t len,uint8_t * value,bool is_notification)430   void OnVolumeControlStateReadOrNotified(VolumeControlDevice* device,
431                                           uint16_t len, uint8_t* value,
432                                           bool is_notification) {
433     if (len != 3) {
434       log::info("malformed len=0x{:x}", len);
435       return;
436     }
437 
438     uint8_t vol;
439     uint8_t mute;
440     uint8_t* pp = value;
441     STREAM_TO_UINT8(vol, pp);
442     STREAM_TO_UINT8(mute, pp);
443     STREAM_TO_UINT8(device->change_counter, pp);
444 
445     bool is_volume_change = (device->volume != vol);
446     device->volume = vol;
447 
448     bool is_mute_change = (device->mute != mute);
449     device->mute = mute;
450 
451     log::info("volume 0x{:x} mute 0x{:x} change_counter 0x{:x}", device->volume,
452               device->mute, device->change_counter);
453 
454     if (!device->IsReady()) {
455       log::info("Device: {} is not ready yet.", device->address);
456       return;
457     }
458 
459     /* This is just a read, send single notification */
460     if (!is_notification) {
461       callbacks_->OnVolumeStateChanged(device->address, device->volume,
462                                        device->mute, false);
463       return;
464     }
465 
466     auto addr = device->address;
467     auto op = find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
468                       [addr](auto& operation) {
469                         auto it = find(operation.devices_.begin(),
470                                        operation.devices_.end(), addr);
471                         return it != operation.devices_.end();
472                       });
473     if (op == ongoing_operations_.end()) {
474       log::debug("Could not find operation id for device: {}. Autonomus change",
475                  device->address);
476       HandleAutonomusVolumeChange(device, is_volume_change, is_mute_change);
477       return;
478     }
479 
480     /* Received notification from the device we do expect */
481     auto it = find(op->devices_.begin(), op->devices_.end(), device->address);
482     op->devices_.erase(it);
483     if (!op->devices_.empty()) {
484       log::debug("wait for more responses for operation_id: {}",
485                  op->operation_id_);
486       return;
487     }
488 
489     if (op->IsGroupOperation()) {
490       callbacks_->OnGroupVolumeStateChanged(op->group_id_, device->volume,
491                                             device->mute, op->is_autonomous_);
492     } else {
493       /* op->is_autonomous_ will always be false,
494          since we only make it true for group operations */
495       callbacks_->OnVolumeStateChanged(device->address, device->volume,
496                                        device->mute, false);
497     }
498 
499     ongoing_operations_.erase(op);
500     StartQueueOperation();
501   }
502 
OnVolumeControlFlagsChanged(VolumeControlDevice * device,uint16_t len,uint8_t * value)503   void OnVolumeControlFlagsChanged(VolumeControlDevice* device, uint16_t len,
504                                    uint8_t* value) {
505     device->flags = *value;
506 
507     log::info("flags 0x{:x}", device->flags);
508   }
509 
OnExtAudioOutStateChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)510   void OnExtAudioOutStateChanged(VolumeControlDevice* device,
511                                  VolumeOffset* offset, uint16_t len,
512                                  uint8_t* value) {
513     if (len != 3) {
514       log::info("malformed len=0x{:x}", len);
515       return;
516     }
517 
518     uint8_t* pp = value;
519     STREAM_TO_UINT16(offset->offset, pp);
520     STREAM_TO_UINT8(offset->change_counter, pp);
521 
522     log::info("{}", base::HexEncode(value, len));
523     log::info("id: 0x{:x} offset: 0x{:x} counter: 0x{:x}", offset->id,
524               offset->offset, offset->change_counter);
525 
526     if (!device->IsReady()) {
527       log::info("Device: {} is not ready yet.", device->address);
528       return;
529     }
530 
531     callbacks_->OnExtAudioOutVolumeOffsetChanged(device->address, offset->id,
532                                                  offset->offset);
533   }
534 
OnExtAudioOutLocationChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)535   void OnExtAudioOutLocationChanged(VolumeControlDevice* device,
536                                     VolumeOffset* offset, uint16_t len,
537                                     uint8_t* value) {
538     if (len != 4) {
539       log::info("malformed len=0x{:x}", len);
540       return;
541     }
542 
543     uint8_t* pp = value;
544     STREAM_TO_UINT32(offset->location, pp);
545 
546     log::info("{}", base::HexEncode(value, len));
547     log::info("id 0x{:x}location 0x{:x}", offset->id, offset->location);
548 
549     if (!device->IsReady()) {
550       log::info("Device: {} is not ready yet.", device->address);
551       return;
552     }
553 
554     callbacks_->OnExtAudioOutLocationChanged(device->address, offset->id,
555                                              offset->location);
556   }
557 
OnExtAudioOutCPWrite(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,void *)558   void OnExtAudioOutCPWrite(uint16_t connection_id, tGATT_STATUS status,
559                             uint16_t handle, void* /*data*/) {
560     VolumeControlDevice* device =
561         volume_control_devices_.FindByConnId(connection_id);
562     if (!device) {
563       log::error("Skipping unknown device disconnect, connection_id=0x{:x}",
564                  connection_id);
565       return;
566     }
567 
568     log::info("Offset Control Point write response handle0x{:x} status: 0x{:x}",
569               handle, (int)(status));
570 
571     /* TODO Design callback API to notify about changes */
572   }
573 
OnOffsetOutputDescChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)574   void OnOffsetOutputDescChanged(VolumeControlDevice* device,
575                                  VolumeOffset* offset, uint16_t len,
576                                  uint8_t* value) {
577     std::string description = std::string(value, value + len);
578     if (!base::IsStringUTF8(description)) description = "<invalid utf8 string>";
579 
580     log::info("{}", description);
581 
582     if (!device->IsReady()) {
583       log::info("Device: {} is not ready yet.", device->address);
584       return;
585     }
586 
587     callbacks_->OnExtAudioOutDescriptionChanged(device->address, offset->id,
588                                                 std::move(description));
589   }
590 
OnGattWriteCcc(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void *)591   void OnGattWriteCcc(uint16_t connection_id, tGATT_STATUS status,
592                       uint16_t handle, uint16_t len, const uint8_t* value,
593                       void* /*data*/) {
594     VolumeControlDevice* device =
595         volume_control_devices_.FindByConnId(connection_id);
596     if (!device) {
597       log::info("unknown connection_id=0x{:x}", connection_id);
598       BtaGattQueue::Clean(connection_id);
599       return;
600     }
601 
602     if (status != GATT_SUCCESS) {
603       if (status == GATT_DATABASE_OUT_OF_SYNC) {
604         log::info("Database out of sync for {}, conn_id: 0x{:04x}",
605                   device->address, connection_id);
606         ClearDeviceInformationAndStartSearch(device);
607       } else {
608         log::error(
609             "Failed to register for notification: 0x{:04x}, status 0x{:02x}",
610             handle, status);
611         device_cleanup_helper(device, true);
612       }
613       return;
614     }
615 
616     log::info("Successfully registered on ccc: 0x{:04x}, device: {}", handle,
617               device->address);
618 
619     verify_device_ready(device, handle);
620   }
621 
OnGattWriteCccStatic(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)622   static void OnGattWriteCccStatic(uint16_t connection_id, tGATT_STATUS status,
623                                    uint16_t handle, uint16_t len,
624                                    const uint8_t* value, void* data) {
625     if (!instance) {
626       log::error("No instance={}", handle);
627       return;
628     }
629 
630     instance->OnGattWriteCcc(connection_id, status, handle, len, value, data);
631   }
632 
Dump(int fd)633   void Dump(int fd) {
634     dprintf(fd, "APP ID: %d\n", gatt_if_);
635     volume_control_devices_.DebugDump(fd);
636   }
637 
Disconnect(const RawAddress & address)638   void Disconnect(const RawAddress& address) override {
639     log::info("{}", address);
640 
641     VolumeControlDevice* device =
642         volume_control_devices_.FindByAddress(address);
643     if (!device) {
644       log::warn("Device not connected to profile {}", address);
645       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
646       return;
647     }
648 
649     log::info("GAP_EVT_CONN_CLOSED: {}", device->address);
650     device->connecting_actively = false;
651     device_cleanup_helper(device, true);
652   }
653 
Remove(const RawAddress & address)654   void Remove(const RawAddress& address) override {
655     log::info("{}", address);
656 
657     /* Removes all registrations for connection. */
658     BTA_GATTC_CancelOpen(gatt_if_, address, false);
659 
660     Disconnect(address);
661     volume_control_devices_.Remove(address);
662   }
663 
OnGattDisconnected(uint16_t connection_id,tGATT_IF,RawAddress remote_bda,tGATT_DISCONN_REASON reason)664   void OnGattDisconnected(uint16_t connection_id, tGATT_IF /*client_if*/,
665                           RawAddress remote_bda, tGATT_DISCONN_REASON reason) {
666     VolumeControlDevice* device =
667         volume_control_devices_.FindByConnId(connection_id);
668     if (!device) {
669       log::error("Skipping unknown device disconnect, connection_id=0x{:x}",
670                  connection_id);
671       return;
672     }
673 
674     if (!device->IsConnected()) {
675       log::error(
676           "Skipping disconnect of the already disconnected device, "
677           "connection_id=0x{:x}",
678           connection_id);
679       return;
680     }
681 
682     log::info("{}", remote_bda);
683 
684     bool notify = device->IsReady() || device->connecting_actively;
685     device_cleanup_helper(device, notify);
686 
687     if (reason != GATT_CONN_TERMINATE_LOCAL_HOST &&
688         device->connecting_actively) {
689       StartOpportunisticConnect(remote_bda);
690     }
691   }
692 
RemoveDeviceFromOperationList(const RawAddress & addr)693   void RemoveDeviceFromOperationList(const RawAddress& addr) {
694     if (ongoing_operations_.empty()) {
695       return;
696     }
697 
698     for (auto& op : ongoing_operations_) {
699       auto it = find(op.devices_.begin(), op.devices_.end(), addr);
700       if (it == op.devices_.end()) {
701         continue;
702       }
703       op.devices_.erase(it);
704     }
705 
706     // Remove operations with no devices
707     ongoing_operations_.erase(
708         std::remove_if(ongoing_operations_.begin(), ongoing_operations_.end(),
709                        [](auto& op) { return op.devices_.empty(); }),
710         ongoing_operations_.end());
711   }
712 
RemoveDeviceFromOperationList(const RawAddress & addr,int operation_id)713   void RemoveDeviceFromOperationList(const RawAddress& addr, int operation_id) {
714     auto op = find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
715                       [operation_id](auto& operation) {
716                         return operation.operation_id_ == operation_id;
717                       });
718 
719     if (op == ongoing_operations_.end()) {
720       log::error("Could not find operation id: {}", operation_id);
721       return;
722     }
723 
724     auto it = find(op->devices_.begin(), op->devices_.end(), addr);
725     if (it != op->devices_.end()) {
726       op->devices_.erase(it);
727       if (op->devices_.empty()) {
728         ongoing_operations_.erase(op);
729         StartQueueOperation();
730       }
731       return;
732     }
733   }
734 
RemovePendingVolumeControlOperations(std::vector<RawAddress> & devices,int group_id)735   void RemovePendingVolumeControlOperations(std::vector<RawAddress>& devices,
736                                             int group_id) {
737     log::debug("");
738     for (auto op = ongoing_operations_.begin();
739          op != ongoing_operations_.end();) {
740       // We only remove operations that don't affect the mute field.
741       if (op->IsStarted() ||
742           (op->opcode_ != kControlPointOpcodeSetAbsoluteVolume &&
743            op->opcode_ != kControlPointOpcodeVolumeUp &&
744            op->opcode_ != kControlPointOpcodeVolumeDown)) {
745         op++;
746         continue;
747       }
748       if (group_id != bluetooth::groups::kGroupUnknown &&
749           op->group_id_ == group_id) {
750         log::debug("Removing operation {}", op->operation_id_);
751         op = ongoing_operations_.erase(op);
752         continue;
753       }
754       for (auto const& addr : devices) {
755         auto it = find(op->devices_.begin(), op->devices_.end(), addr);
756         if (it != op->devices_.end()) {
757           log::debug("Removing {} from operation", *it);
758           op->devices_.erase(it);
759         }
760       }
761       if (op->devices_.empty()) {
762         op = ongoing_operations_.erase(op);
763         log::debug("Removing operation {}", op->operation_id_);
764       } else {
765         op++;
766       }
767     }
768   }
769 
OnWriteControlResponse(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,void * data)770   void OnWriteControlResponse(uint16_t connection_id, tGATT_STATUS status,
771                               uint16_t handle, void* data) {
772     VolumeControlDevice* device =
773         volume_control_devices_.FindByConnId(connection_id);
774     if (!device) {
775       log::error("Skipping unknown device disconnect, connection_id=0x{:x}",
776                  connection_id);
777       return;
778     }
779 
780     log::info("Write response handle: 0x{:x} status: 0x{:x}", handle,
781               (int)(status));
782 
783     if (status == GATT_SUCCESS) return;
784 
785     /* In case of error, remove device from the tracking operation list */
786     RemoveDeviceFromOperationList(device->address, PTR_TO_INT(data));
787 
788     if (status == GATT_DATABASE_OUT_OF_SYNC) {
789       log::info("Database out of sync for {}", device->address);
790       ClearDeviceInformationAndStartSearch(device);
791     }
792   }
793 
operation_timeout_callback(void * data)794   static void operation_timeout_callback(void* data) {
795     if (!instance) {
796       log::warn("There is no instance.");
797       return;
798     }
799     instance->OperationMonitorTimeoutFired(PTR_TO_INT(data));
800   }
801 
OperationMonitorTimeoutFired(int operation_id)802   void OperationMonitorTimeoutFired(int operation_id) {
803     auto op = find_if(
804         ongoing_operations_.begin(), ongoing_operations_.end(),
805         [operation_id](auto& it) { return it.operation_id_ == operation_id; });
806 
807     if (op == ongoing_operations_.end()) {
808       log::error("Could not find operation_id: {}", operation_id);
809       return;
810     }
811 
812     log::warn("Operation {} is taking too long for devices:", operation_id);
813     for (const auto& addr : op->devices_) {
814       log::warn("{},", addr);
815     }
816     alarm_set_on_mloop(op->operation_timeout_, kOperationMonitorTimeoutMs,
817                        operation_timeout_callback, INT_TO_PTR(operation_id));
818   }
819 
StartQueueOperation(void)820   void StartQueueOperation(void) {
821     log::info("");
822     if (ongoing_operations_.empty()) {
823       return;
824     };
825 
826     auto op = &ongoing_operations_.front();
827 
828     log::info("Current operation_id: {}", op->operation_id_);
829 
830     if (op->IsStarted()) {
831       log::info("Operation {} is started, wait until it is complete",
832                 op->operation_id_);
833       return;
834     }
835 
836     op->Start();
837 
838     alarm_set_on_mloop(op->operation_timeout_, kOperationMonitorTimeoutMs,
839                        operation_timeout_callback,
840                        INT_TO_PTR(op->operation_id_));
841     devices_control_point_helper(
842         op->devices_, op->opcode_,
843         op->arguments_.size() == 0 ? nullptr : &(op->arguments_),
844         op->operation_id_);
845   }
846 
PrepareVolumeControlOperation(std::vector<RawAddress> devices,int group_id,bool is_autonomous,uint8_t opcode,std::vector<uint8_t> & arguments)847   void PrepareVolumeControlOperation(std::vector<RawAddress> devices,
848                                      int group_id, bool is_autonomous,
849                                      uint8_t opcode,
850                                      std::vector<uint8_t>& arguments) {
851     log::debug(
852         "num of devices: {}, group_id: {}, is_autonomous: {}  opcode: {}, arg "
853         "size: {}",
854         devices.size(), group_id, is_autonomous, opcode, arguments.size());
855 
856     if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
857                      [opcode, &devices, &arguments](const VolumeOperation& op) {
858                        if (op.opcode_ != opcode) return false;
859                        if (!std::equal(op.arguments_.begin(),
860                                        op.arguments_.end(), arguments.begin()))
861                          return false;
862                        // Filter out all devices which have the exact operation
863                        // already scheduled
864                        devices.erase(
865                            std::remove_if(devices.begin(), devices.end(),
866                                           [&op](auto d) {
867                                             return find(op.devices_.begin(),
868                                                         op.devices_.end(),
869                                                         d) != op.devices_.end();
870                                           }),
871                            devices.end());
872                        return devices.empty();
873                      }) == ongoing_operations_.end()) {
874       ongoing_operations_.emplace_back(latest_operation_id_++, group_id,
875                                        is_autonomous, opcode, arguments,
876                                        devices);
877     }
878   }
879 
MuteUnmute(std::variant<RawAddress,int> addr_or_group_id,bool mute)880   void MuteUnmute(std::variant<RawAddress, int> addr_or_group_id, bool mute) {
881     std::vector<uint8_t> arg;
882 
883     uint8_t opcode = mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute;
884 
885     if (std::holds_alternative<RawAddress>(addr_or_group_id)) {
886       VolumeControlDevice* dev = volume_control_devices_.FindByAddress(
887           std::get<RawAddress>(addr_or_group_id));
888       if (dev != nullptr) {
889         log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady());
890         if (dev->IsReady() && (dev->mute != mute)) {
891           std::vector<RawAddress> devices = {dev->address};
892           PrepareVolumeControlOperation(
893               devices, bluetooth::groups::kGroupUnknown, false, opcode, arg);
894         }
895       }
896     } else {
897       /* Handle group change */
898       auto group_id = std::get<int>(addr_or_group_id);
899       log::debug("group: {}", group_id);
900       auto csis_api = CsisClient::Get();
901       if (!csis_api) {
902         log::error("Csis is not there");
903         return;
904       }
905 
906       auto devices = csis_api->GetDeviceList(group_id);
907       if (devices.empty()) {
908         log::error("group id: {} has no devices", group_id);
909         return;
910       }
911 
912       bool muteNotChanged = false;
913       bool deviceNotReady = false;
914 
915       for (auto it = devices.begin(); it != devices.end();) {
916         auto dev = volume_control_devices_.FindByAddress(*it);
917         if (!dev) {
918           it = devices.erase(it);
919           continue;
920         }
921 
922         if (!dev->IsReady() || (dev->mute == mute)) {
923           it = devices.erase(it);
924           muteNotChanged =
925               muteNotChanged ? muteNotChanged : (dev->mute == mute);
926           deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
927           continue;
928         }
929         it++;
930       }
931 
932       if (devices.empty()) {
933         log::debug(
934             "No need to update mute for group id: {} . muteNotChanged: {}, "
935             "deviceNotReady: {}",
936             group_id, muteNotChanged, deviceNotReady);
937         return;
938       }
939 
940       PrepareVolumeControlOperation(devices, group_id, false, opcode, arg);
941     }
942 
943     StartQueueOperation();
944   }
945 
Mute(std::variant<RawAddress,int> addr_or_group_id)946   void Mute(std::variant<RawAddress, int> addr_or_group_id) override {
947     log::debug("");
948     MuteUnmute(addr_or_group_id, true /* mute */);
949   }
950 
UnMute(std::variant<RawAddress,int> addr_or_group_id)951   void UnMute(std::variant<RawAddress, int> addr_or_group_id) override {
952     log::debug("");
953     MuteUnmute(addr_or_group_id, false /* mute */);
954   }
955 
SetVolume(std::variant<RawAddress,int> addr_or_group_id,uint8_t volume)956   void SetVolume(std::variant<RawAddress, int> addr_or_group_id,
957                  uint8_t volume) override {
958     std::vector<uint8_t> arg({volume});
959     uint8_t opcode = kControlPointOpcodeSetAbsoluteVolume;
960 
961     if (std::holds_alternative<RawAddress>(addr_or_group_id)) {
962       log::debug("Address: {}:", std::get<RawAddress>(addr_or_group_id));
963       VolumeControlDevice* dev = volume_control_devices_.FindByAddress(
964           std::get<RawAddress>(addr_or_group_id));
965       if (dev != nullptr) {
966         log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady());
967         if (dev->IsReady() && (dev->volume != volume)) {
968           std::vector<RawAddress> devices = {dev->address};
969           RemovePendingVolumeControlOperations(
970               devices, bluetooth::groups::kGroupUnknown);
971           PrepareVolumeControlOperation(
972               devices, bluetooth::groups::kGroupUnknown, false, opcode, arg);
973         }
974       }
975     } else {
976       /* Handle group change */
977       auto group_id = std::get<int>(addr_or_group_id);
978       log::debug("group_id: {}, vol: {}", group_id, volume);
979       auto csis_api = CsisClient::Get();
980       if (!csis_api) {
981         log::error("Csis is not there");
982         return;
983       }
984 
985       auto devices = csis_api->GetDeviceList(group_id);
986       if (devices.empty()) {
987         log::error("group id: {} has no devices", group_id);
988         return;
989       }
990 
991       bool volumeNotChanged = false;
992       bool deviceNotReady = false;
993 
994       for (auto it = devices.begin(); it != devices.end();) {
995         auto dev = volume_control_devices_.FindByAddress(*it);
996         if (!dev) {
997           it = devices.erase(it);
998           continue;
999         }
1000 
1001         if (!dev->IsReady() || (dev->volume == volume)) {
1002           it = devices.erase(it);
1003           volumeNotChanged =
1004               volumeNotChanged ? volumeNotChanged : (dev->volume == volume);
1005           deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
1006           continue;
1007         }
1008 
1009         it++;
1010       }
1011 
1012       if (devices.empty()) {
1013         log::debug(
1014             "No need to update volume for group id: {} . volumeNotChanged: {}, "
1015             "deviceNotReady: {}",
1016             group_id, volumeNotChanged, deviceNotReady);
1017         return;
1018       }
1019 
1020       RemovePendingVolumeControlOperations(devices, group_id);
1021       PrepareVolumeControlOperation(devices, group_id, false, opcode, arg);
1022     }
1023 
1024     StartQueueOperation();
1025   }
1026 
1027   /* Methods to operate on Volume Control Offset Service (VOCS) */
GetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id)1028   void GetExtAudioOutVolumeOffset(const RawAddress& address,
1029                                   uint8_t ext_output_id) override {
1030     VolumeControlDevice* device =
1031         volume_control_devices_.FindByAddress(address);
1032     if (!device) {
1033       log::error("no such device!");
1034       return;
1035     }
1036 
1037     device->GetExtAudioOutVolumeOffset(ext_output_id, chrc_read_callback_static,
1038                                        nullptr);
1039   }
1040 
SetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id,int16_t offset_val)1041   void SetExtAudioOutVolumeOffset(const RawAddress& address,
1042                                   uint8_t ext_output_id,
1043                                   int16_t offset_val) override {
1044     std::vector<uint8_t> arg(2);
1045     uint8_t* ptr = arg.data();
1046     UINT16_TO_STREAM(ptr, offset_val);
1047     ext_audio_out_control_point_helper(
1048         address, ext_output_id, kVolumeOffsetControlPointOpcodeSet, &arg);
1049   }
1050 
GetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id)1051   void GetExtAudioOutLocation(const RawAddress& address,
1052                               uint8_t ext_output_id) override {
1053     VolumeControlDevice* device =
1054         volume_control_devices_.FindByAddress(address);
1055     if (!device) {
1056       log::error("no such device!");
1057       return;
1058     }
1059 
1060     device->GetExtAudioOutLocation(ext_output_id, chrc_read_callback_static,
1061                                    nullptr);
1062   }
1063 
SetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id,uint32_t location)1064   void SetExtAudioOutLocation(const RawAddress& address, uint8_t ext_output_id,
1065                               uint32_t location) override {
1066     VolumeControlDevice* device =
1067         volume_control_devices_.FindByAddress(address);
1068     if (!device) {
1069       log::error("no such device!");
1070       return;
1071     }
1072 
1073     device->SetExtAudioOutLocation(ext_output_id, location);
1074   }
1075 
GetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id)1076   void GetExtAudioOutDescription(const RawAddress& address,
1077                                  uint8_t ext_output_id) override {
1078     VolumeControlDevice* device =
1079         volume_control_devices_.FindByAddress(address);
1080     if (!device) {
1081       log::error("no such device!");
1082       return;
1083     }
1084 
1085     device->GetExtAudioOutDescription(ext_output_id, chrc_read_callback_static,
1086                                       nullptr);
1087   }
1088 
SetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id,std::string descr)1089   void SetExtAudioOutDescription(const RawAddress& address,
1090                                  uint8_t ext_output_id,
1091                                  std::string descr) override {
1092     VolumeControlDevice* device =
1093         volume_control_devices_.FindByAddress(address);
1094     if (!device) {
1095       log::error("no such device!");
1096       return;
1097     }
1098 
1099     device->SetExtAudioOutDescription(ext_output_id, descr);
1100   }
1101 
CleanUp()1102   void CleanUp() {
1103     log::info("");
1104     volume_control_devices_.Disconnect(gatt_if_);
1105     volume_control_devices_.Clear();
1106     ongoing_operations_.clear();
1107     BTA_GATTC_AppDeregister(gatt_if_);
1108   }
1109 
1110  private:
1111   tGATT_IF gatt_if_;
1112   bluetooth::vc::VolumeControlCallbacks* callbacks_;
1113   VolumeControlDevices volume_control_devices_;
1114 
1115   /* Used to track volume control operations */
1116   std::list<VolumeOperation> ongoing_operations_;
1117   int latest_operation_id_;
1118 
1119   static constexpr uint64_t kOperationMonitorTimeoutMs = 3000;
1120 
verify_device_ready(VolumeControlDevice * device,uint16_t handle)1121   void verify_device_ready(VolumeControlDevice* device, uint16_t handle) {
1122     if (device->IsReady()) return;
1123 
1124     // VerifyReady sets the device_ready flag if all remaining GATT operations
1125     // are completed
1126     if (device->VerifyReady(handle)) {
1127       log::info("Outstanding reads completed.");
1128 
1129       callbacks_->OnDeviceAvailable(device->address,
1130                                     device->audio_offsets.Size());
1131       callbacks_->OnConnectionState(ConnectionState::CONNECTED,
1132                                     device->address);
1133 
1134       // once profile connected we can notify current states
1135       callbacks_->OnVolumeStateChanged(device->address, device->volume,
1136                                        device->mute, false);
1137 
1138       for (auto const& offset : device->audio_offsets.volume_offsets) {
1139         callbacks_->OnExtAudioOutVolumeOffsetChanged(device->address, offset.id,
1140                                                      offset.offset);
1141       }
1142 
1143       device->EnqueueRemainingRequests(gatt_if_, chrc_read_callback_static,
1144                                        OnGattWriteCccStatic);
1145     }
1146   }
1147 
device_cleanup_helper(VolumeControlDevice * device,bool notify)1148   void device_cleanup_helper(VolumeControlDevice* device, bool notify) {
1149     device->Disconnect(gatt_if_);
1150 
1151     RemoveDeviceFromOperationList(device->address);
1152 
1153     if (notify)
1154       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED,
1155                                     device->address);
1156   }
1157 
devices_control_point_helper(std::vector<RawAddress> & devices,uint8_t opcode,const std::vector<uint8_t> * arg,int operation_id=-1)1158   void devices_control_point_helper(std::vector<RawAddress>& devices,
1159                                     uint8_t opcode,
1160                                     const std::vector<uint8_t>* arg,
1161                                     int operation_id = -1) {
1162     volume_control_devices_.ControlPointOperation(
1163         devices, opcode, arg,
1164         [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle,
1165            uint16_t len, const uint8_t* value, void* data) {
1166           if (instance)
1167             instance->OnWriteControlResponse(connection_id, status, handle,
1168                                              data);
1169         },
1170         INT_TO_PTR(operation_id));
1171   }
1172 
ext_audio_out_control_point_helper(const RawAddress & address,uint8_t ext_output_id,uint8_t opcode,const std::vector<uint8_t> * arg)1173   void ext_audio_out_control_point_helper(const RawAddress& address,
1174                                           uint8_t ext_output_id, uint8_t opcode,
1175                                           const std::vector<uint8_t>* arg) {
1176     log::info("{} id=0x{:x} op=0x{:x}", address, ext_output_id, opcode);
1177     VolumeControlDevice* device =
1178         volume_control_devices_.FindByAddress(address);
1179     if (!device) {
1180       log::error("no such device!");
1181       return;
1182     }
1183     device->ExtAudioOutControlPointOperation(
1184         ext_output_id, opcode, arg,
1185         [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle,
1186            uint16_t len, const uint8_t* value, void* data) {
1187           if (instance)
1188             instance->OnExtAudioOutCPWrite(connection_id, status, handle, data);
1189         },
1190         nullptr);
1191   }
1192 
gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1193   void gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1194     log::info("event = {}", static_cast<int>(event));
1195 
1196     if (p_data == nullptr) return;
1197 
1198     switch (event) {
1199       case BTA_GATTC_OPEN_EVT: {
1200         tBTA_GATTC_OPEN& o = p_data->open;
1201         OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda,
1202                         o.transport, o.mtu);
1203 
1204       } break;
1205 
1206       case BTA_GATTC_CLOSE_EVT: {
1207         tBTA_GATTC_CLOSE& c = p_data->close;
1208         OnGattDisconnected(c.conn_id, c.client_if, c.remote_bda, c.reason);
1209       } break;
1210 
1211       case BTA_GATTC_SEARCH_CMPL_EVT:
1212         OnServiceSearchComplete(p_data->search_cmpl.conn_id,
1213                                 p_data->search_cmpl.status);
1214         break;
1215 
1216       case BTA_GATTC_NOTIF_EVT: {
1217         tBTA_GATTC_NOTIFY& n = p_data->notify;
1218         if (!n.is_notify || n.len > GATT_MAX_ATTR_LEN) {
1219           log::error("rejected BTA_GATTC_NOTIF_EVT. is_notify={}, len={}",
1220                      n.is_notify, static_cast<int>(n.len));
1221           break;
1222         }
1223         OnNotificationEvent(n.conn_id, n.handle, n.len, n.value);
1224       } break;
1225 
1226       case BTA_GATTC_ENC_CMPL_CB_EVT: {
1227         uint8_t encryption_status;
1228         if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
1229           encryption_status = BTM_SUCCESS;
1230         } else {
1231           encryption_status = BTM_FAILED_ON_SECURITY;
1232         }
1233         OnEncryptionComplete(p_data->enc_cmpl.remote_bda, encryption_status);
1234       } break;
1235 
1236       case BTA_GATTC_SRVC_CHG_EVT:
1237         OnServiceChangeEvent(p_data->remote_bda);
1238         break;
1239 
1240       case BTA_GATTC_SRVC_DISC_DONE_EVT:
1241         OnServiceDiscDoneEvent(p_data->remote_bda);
1242         break;
1243 
1244       default:
1245         break;
1246     }
1247   }
1248 
gattc_callback_static(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1249   static void gattc_callback_static(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1250     if (instance) instance->gattc_callback(event, p_data);
1251   }
1252 
chrc_read_callback_static(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)1253   static void chrc_read_callback_static(uint16_t conn_id, tGATT_STATUS status,
1254                                         uint16_t handle, uint16_t len,
1255                                         uint8_t* value, void* data) {
1256     if (instance)
1257       instance->OnCharacteristicValueChanged(conn_id, status, handle, len,
1258                                              value, data, false);
1259   }
1260 };
1261 }  // namespace
1262 
Initialize(bluetooth::vc::VolumeControlCallbacks * callbacks,const base::Closure & initCb)1263 void VolumeControl::Initialize(bluetooth::vc::VolumeControlCallbacks* callbacks,
1264                                const base::Closure& initCb) {
1265   std::scoped_lock<std::mutex> lock(instance_mutex);
1266   if (instance) {
1267     log::error("Already initialized!");
1268     return;
1269   }
1270 
1271   instance = new VolumeControlImpl(callbacks, initCb);
1272 }
1273 
IsVolumeControlRunning()1274 bool VolumeControl::IsVolumeControlRunning() { return instance; }
1275 
Get(void)1276 VolumeControl* VolumeControl::Get(void) {
1277   log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
1278   return instance;
1279 };
1280 
AddFromStorage(const RawAddress & address)1281 void VolumeControl::AddFromStorage(const RawAddress& address) {
1282   if (!instance) {
1283     log::error("Not initialized yet");
1284     return;
1285   }
1286 
1287   instance->AddFromStorage(address);
1288 };
1289 
CleanUp()1290 void VolumeControl::CleanUp() {
1291   std::scoped_lock<std::mutex> lock(instance_mutex);
1292   if (!instance) {
1293     log::error("Not initialized!");
1294     return;
1295   }
1296 
1297   VolumeControlImpl* ptr = instance;
1298   instance = nullptr;
1299 
1300   ptr->CleanUp();
1301 
1302   delete ptr;
1303 };
1304 
DebugDump(int fd)1305 void VolumeControl::DebugDump(int fd) {
1306   std::scoped_lock<std::mutex> lock(instance_mutex);
1307   dprintf(fd, "Volume Control Manager:\n");
1308   if (instance) instance->Dump(fd);
1309   dprintf(fd, "\n");
1310 }
1311