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