• 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 <aics/api.h>
19 #include <base/functional/bind.h>
20 #include <base/strings/string_number_conversions.h>
21 #include <base/strings/string_util.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24 #include <hardware/bt_gatt_types.h>
25 #include <hardware/bt_vc.h>
26 #include <stdio.h>
27 
28 #include <algorithm>
29 #include <cstddef>
30 #include <cstdint>
31 #include <list>
32 #include <mutex>
33 #include <string>
34 #include <variant>
35 #include <vector>
36 
37 #include "bta/include/bta_csis_api.h"
38 #include "bta/include/bta_gatt_api.h"
39 #include "bta/include/bta_gatt_queue.h"
40 #include "bta/include/bta_vc_api.h"
41 #include "bta/le_audio/le_audio_types.h"
42 #include "bta/vc/devices.h"
43 #include "bta_groups.h"
44 #include "btm_ble_api_types.h"
45 #include "gatt/database.h"
46 #include "gatt_api.h"
47 #include "osi/include/alarm.h"
48 #include "osi/include/osi.h"
49 #include "stack/btm/btm_sec.h"
50 #include "stack/include/bt_types.h"
51 #include "stack/include/btm_status.h"
52 #include "types/bluetooth/uuid.h"
53 #include "types/bt_transport.h"
54 #include "types/raw_address.h"
55 #include "vc/types.h"
56 
57 using base::Closure;
58 using bluetooth::csis::CsisClient;
59 using bluetooth::vc::ConnectionState;
60 using bluetooth::vc::VolumeInputStatus;
61 using bluetooth::vc::VolumeInputType;
62 using bluetooth::vc::internal::kControlPointOpcodeMute;
63 using bluetooth::vc::internal::kControlPointOpcodeSetAbsoluteVolume;
64 using bluetooth::vc::internal::kControlPointOpcodeUnmute;
65 using bluetooth::vc::internal::kControlPointOpcodeVolumeDown;
66 using bluetooth::vc::internal::kControlPointOpcodeVolumeUp;
67 using bluetooth::vc::internal::kVolumeControlUuid;
68 using bluetooth::vc::internal::kVolumeInputControlPointOpcodeMute;
69 using bluetooth::vc::internal::kVolumeInputControlPointOpcodeSetAutoGainMode;
70 using bluetooth::vc::internal::kVolumeInputControlPointOpcodeSetGain;
71 using bluetooth::vc::internal::kVolumeInputControlPointOpcodeSetManualGainMode;
72 using bluetooth::vc::internal::kVolumeInputControlPointOpcodeUnmute;
73 using bluetooth::vc::internal::kVolumeOffsetControlPointOpcodeSet;
74 using bluetooth::vc::internal::VolumeAudioInput;
75 using bluetooth::vc::internal::VolumeControlDevice;
76 using bluetooth::vc::internal::VolumeControlDevices;
77 using bluetooth::vc::internal::VolumeOffset;
78 using bluetooth::vc::internal::VolumeOperation;
79 
80 namespace {
81 class VolumeControlImpl;
82 VolumeControlImpl* instance;
83 std::mutex instance_mutex;
84 
85 /**
86  * Overview:
87  *
88  * This is Volume Control Implementation class which realize Volume Control
89  * Profile (VCP)
90  *
91  * Each connected peer device supporting Volume Control Service (VCS) is on the
92  * list of devices (volume_control_devices_). When VCS is discovered on the peer
93  * device, Android does search for all the instances Volume Offset Service
94  * (VOCS). Note that AIS and VOCS are optional.
95  *
96  * Once all the mandatory characteristis for all the services are discovered,
97  * Fluoride calls ON_CONNECTED callback.
98  *
99  * It is assumed that whenever application changes general audio options in this
100  * profile e.g. Volume up/down, mute/unmute etc, profile configures all the
101  * devices which are active Le Audio devices.
102  *
103  * Peer devices has at maximum one instance of VCS and 0 or more instance of
104  * VOCS. Android gets access to External Audio Outputs using appropriate ID.
105  * Also each of the External Device has description
106  * characteristic and Type which gives the application hint what it is a device.
107  * Examples of such devices:
108  *   External Output: 1 instance to controller balance between set of devices
109  *   External Output: each of 5.1 speaker set etc.
110  */
111 class VolumeControlImpl : public VolumeControl {
112 public:
113   ~VolumeControlImpl() override = default;
114 
VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks * callbacks,const base::Closure & initCb)115   VolumeControlImpl(bluetooth::vc::VolumeControlCallbacks* callbacks, const base::Closure& initCb)
116       : gatt_if_(0), callbacks_(callbacks), latest_operation_id_(0) {
117     BTA_GATTC_AppRegister(
118             "volume_control", gattc_callback_static,
119             base::Bind(
120                     [](const base::Closure& initCb, uint8_t client_id, uint8_t status) {
121                       if (status != GATT_SUCCESS) {
122                         bluetooth::log::error(
123                                 "Can't start Volume Control profile - no gatt clients "
124                                 "left!");
125                         return;
126                       }
127                       instance->gatt_if_ = client_id;
128                       initCb.Run();
129                     },
130                     initCb),
131             true);
132   }
133 
StartOpportunisticConnect(const RawAddress & address)134   void StartOpportunisticConnect(const RawAddress& address) {
135     /* Oportunistic works only for direct connect,
136      * but in fact this is background connect
137      */
138     bluetooth::log::info(": {}", address);
139     BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, true);
140   }
141 
Connect(const RawAddress & address)142   void Connect(const RawAddress& address) override {
143     bluetooth::log::info(": {}", address);
144 
145     auto device = volume_control_devices_.FindByAddress(address);
146     if (!device) {
147       if (!BTM_IsBonded(address, BT_TRANSPORT_LE)) {
148         bluetooth::log::error("Connecting  {} when not bonded", address);
149         callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
150         return;
151       }
152       volume_control_devices_.Add(address, true);
153     } else {
154       device->connecting_actively = true;
155 
156       if (device->IsConnected()) {
157         bluetooth::log::warn("address={}, connection_id={} already connected.", address,
158                              device->connection_id);
159 
160         if (device->IsReady()) {
161           callbacks_->OnConnectionState(ConnectionState::CONNECTED, device->address);
162         } else {
163           OnGattConnected(GATT_SUCCESS, device->connection_id, gatt_if_, device->address,
164                           BT_TRANSPORT_LE, GATT_MAX_MTU_SIZE);
165         }
166         return;
167       }
168     }
169 
170     StartOpportunisticConnect(address);
171   }
172 
AddFromStorage(const RawAddress & address)173   void AddFromStorage(const RawAddress& address) {
174     bluetooth::log::info("{}", address);
175     volume_control_devices_.Add(address, false);
176     StartOpportunisticConnect(address);
177   }
178 
OnGattConnected(tGATT_STATUS status,tCONN_ID connection_id,tGATT_IF,RawAddress address,tBT_TRANSPORT transport,uint16_t mtu)179   void OnGattConnected(tGATT_STATUS status, tCONN_ID connection_id, tGATT_IF /*client_if*/,
180                        RawAddress address, tBT_TRANSPORT transport, uint16_t mtu) {
181     bluetooth::log::info("{}, conn_id=0x{:04x}, transport={}, status={}(0x{:02x})", address,
182                          connection_id, bt_transport_text(transport), gatt_status_text(status),
183                          status);
184 
185     if (transport != BT_TRANSPORT_LE) {
186       bluetooth::log::warn("Only LE connection is allowed (transport {})",
187                            bt_transport_text(transport));
188       BTA_GATTC_Close(connection_id);
189       return;
190     }
191 
192     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
193     if (!device) {
194       bluetooth::log::error("Skipping unknown device, address={}", address);
195       return;
196     }
197 
198     if (status != GATT_SUCCESS) {
199       bluetooth::log::info("Failed to connect to Volume Control device");
200       device_cleanup_helper(device, device->connecting_actively);
201       StartOpportunisticConnect(address);
202       return;
203     }
204 
205     device->connection_id = connection_id;
206     device->mtu_ = mtu;
207 
208     /* Make sure to remove device from background connect.
209      * It will be added back if needed, when device got disconnected
210      */
211     BTA_GATTC_CancelOpen(gatt_if_, address, true);
212 
213     if (device->IsEncryptionEnabled()) {
214       OnEncryptionComplete(address, tBTM_STATUS::BTM_SUCCESS);
215       return;
216     }
217 
218     if (!device->EnableEncryption()) {
219       bluetooth::log::error("Link key is not known for {}, disconnect profile", address);
220       device->Disconnect(gatt_if_);
221     }
222   }
223 
OnEncryptionComplete(const RawAddress & address,tBTM_STATUS success)224   void OnEncryptionComplete(const RawAddress& address, tBTM_STATUS success) {
225     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
226     if (!device) {
227       bluetooth::log::error("Skipping unknown device {}", address);
228       return;
229     }
230 
231     if (success != tBTM_STATUS::BTM_SUCCESS) {
232       bluetooth::log::error("encryption failed status: {}", btm_status_text(success));
233       // If the encryption failed, do not remove the device.
234       // Disconnect only, since the Android will try to re-enable encryption
235       // after disconnection
236       device_cleanup_helper(device, device->connecting_actively);
237       return;
238     }
239 
240     bluetooth::log::info("{} status: {}", address, success);
241 
242     if (device->HasHandles()) {
243       device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static, OnGattWriteCccStatic);
244 
245     } else {
246       BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
247     }
248   }
249 
ClearDeviceInformationAndStartSearch(VolumeControlDevice * device)250   void ClearDeviceInformationAndStartSearch(VolumeControlDevice* device) {
251     if (!device) {
252       bluetooth::log::error("Device is null");
253       return;
254     }
255 
256     bluetooth::log::info("address={}", device->address);
257     if (device->known_service_handles_ == false) {
258       bluetooth::log::info("Device already is waiting for new services");
259       return;
260     }
261 
262     std::vector<RawAddress> devices = {device->address};
263     device->DeregisterNotifications(gatt_if_);
264 
265     if (com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
266       RemoveNotStartedPendingOperations(devices, bluetooth::groups::kGroupUnknown, {});
267     } else {
268       RemoveNotStartedPendingOperations(devices, bluetooth::groups::kGroupUnknown,
269                                         {kControlPointOpcodeVolumeDown, kControlPointOpcodeVolumeUp,
270                                          kControlPointOpcodeSetAbsoluteVolume});
271     }
272 
273     device->ResetHandles();
274     BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
275   }
276 
OnServiceChangeEvent(const RawAddress & address)277   void OnServiceChangeEvent(const RawAddress& address) {
278     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
279     if (!device) {
280       bluetooth::log::error("Skipping unknown device {}", address);
281       return;
282     }
283 
284     ClearDeviceInformationAndStartSearch(device);
285   }
286 
OnMtuChanged(tCONN_ID conn_id,uint16_t mtu)287   void OnMtuChanged(tCONN_ID conn_id, uint16_t mtu) {
288     VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id);
289     if (!device) {
290       bluetooth::log::error("Skipping unknown device conn_id: {}", conn_id);
291       return;
292     }
293     device->mtu_ = mtu;
294   }
295 
OnServiceDiscDoneEvent(const RawAddress & address)296   void OnServiceDiscDoneEvent(const RawAddress& address) {
297     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
298     if (!device) {
299       bluetooth::log::error("Skipping unknown device {}", address);
300       return;
301     }
302 
303     if (device->known_service_handles_ == false) {
304       BTA_GATTC_ServiceSearchRequest(device->connection_id, kVolumeControlUuid);
305     }
306   }
307 
OnServiceSearchComplete(tCONN_ID connection_id,tGATT_STATUS status)308   void OnServiceSearchComplete(tCONN_ID connection_id, tGATT_STATUS status) {
309     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
310     if (!device) {
311       bluetooth::log::error("Skipping unknown device, connection_id={:#x}", connection_id);
312       return;
313     }
314 
315     /* Known device, nothing to do */
316     if (device->IsReady()) {
317       return;
318     }
319 
320     if (status != GATT_SUCCESS) {
321       /* close connection and report service discovery complete with error */
322       bluetooth::log::error("Service discovery failed");
323       device_cleanup_helper(device, device->connecting_actively);
324       return;
325     }
326 
327     if (!device->IsEncryptionEnabled()) {
328       bluetooth::log::warn("Device not yet bonded - waiting for encryption");
329       return;
330     }
331 
332     bool success = device->UpdateHandles();
333     if (!success) {
334       bluetooth::log::error("Incomplete service database");
335       device_cleanup_helper(device, device->connecting_actively);
336       return;
337     }
338 
339     device->EnqueueInitialRequests(gatt_if_, chrc_read_callback_static, OnGattWriteCccStatic);
340   }
341 
OnCharacteristicValueChanged(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void *,bool is_notification)342   void OnCharacteristicValueChanged(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle,
343                                     uint16_t len, uint8_t* value, void* /*data*/,
344                                     bool is_notification) {
345     VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id);
346     if (!device) {
347       bluetooth::log::error("unknown conn_id={:#x}", conn_id);
348       return;
349     }
350 
351     if (status != GATT_SUCCESS) {
352       bluetooth::log::info("status=0x{:02x}", static_cast<int>(status));
353       if (status == GATT_DATABASE_OUT_OF_SYNC) {
354         bluetooth::log::info("Database out of sync for {}", device->address);
355         ClearDeviceInformationAndStartSearch(device);
356       }
357       return;
358     }
359 
360     if (handle == device->volume_state_handle) {
361       OnVolumeControlStateReadOrNotified(device, len, value, is_notification);
362       verify_device_ready(device, handle);
363       return;
364     }
365     if (handle == device->volume_flags_handle) {
366       OnVolumeControlFlagsChanged(device, len, value);
367       verify_device_ready(device, handle);
368       return;
369     }
370 
371     const gatt::Service* service = BTA_GATTC_GetOwningService(conn_id, handle);
372     if (service == nullptr) {
373       return;
374     }
375 
376     VolumeAudioInput* input = device->audio_inputs.FindByServiceHandle(service->handle);
377     if (input != nullptr) {
378       if (handle == input->state_handle) {
379         OnExtAudioInputStateChanged(device, input, len, value);
380       } else if (handle == input->type_handle) {
381         OnExtAudioInTypeChanged(device, input, len, value);
382       } else if (handle == input->status_handle) {
383         OnExtAudioInputStatusChanged(device, input, len, value);
384       } else if (handle == input->description_handle) {
385         OnExtAudioInDescChanged(device, input, len, value);
386       } else if (handle == input->gain_setting_handle) {
387         OnExtAudioInGainSettingChanged(device, input, len, value);
388       } else {
389         bluetooth::log::error("{} unknown input handle={:#x}", device->address, handle);
390         return;
391       }
392 
393       verify_device_ready(device, handle);
394       return;
395     }
396 
397     VolumeOffset* offset = device->audio_offsets.FindByServiceHandle(service->handle);
398     if (offset != nullptr) {
399       if (handle == offset->state_handle) {
400         OnExtAudioOutStateChanged(device, offset, len, value);
401       } else if (handle == offset->audio_location_handle) {
402         OnExtAudioOutLocationChanged(device, offset, len, value);
403       } else if (handle == offset->audio_descr_handle) {
404         OnOffsetOutputDescChanged(device, offset, len, value);
405       } else {
406         bluetooth::log::error("{} unknown offset handle={:#x}", device->address, handle);
407         return;
408       }
409 
410       verify_device_ready(device, handle);
411       return;
412     }
413 
414     bluetooth::log::error("{}, unknown handle={:#x}", device->address, handle);
415   }
416 
OnNotificationEvent(tCONN_ID conn_id,uint16_t handle,uint16_t len,uint8_t * value)417   void OnNotificationEvent(tCONN_ID conn_id, uint16_t handle, uint16_t len, uint8_t* value) {
418     bluetooth::log::info("connection_id={:#x}, handle={:#x}", conn_id, handle);
419     OnCharacteristicValueChanged(conn_id, GATT_SUCCESS, handle, len, value, nullptr, true);
420   }
421 
VolumeControlReadCommon(tCONN_ID conn_id,uint16_t handle)422   void VolumeControlReadCommon(tCONN_ID conn_id, uint16_t handle) {
423     BtaGattQueue::ReadCharacteristic(conn_id, handle, chrc_read_callback_static, nullptr);
424   }
425 
HandleAutonomusVolumeChange(VolumeControlDevice * device,bool is_volume_change,bool is_mute_change)426   void HandleAutonomusVolumeChange(VolumeControlDevice* device, bool is_volume_change,
427                                    bool is_mute_change) {
428     bluetooth::log::debug("{}, is volume change: {}, is mute change: {}", device->address,
429                           is_volume_change, is_mute_change);
430 
431     if (!is_volume_change && !is_mute_change) {
432       bluetooth::log::warn("Autonomous change but volume and mute did not changed.");
433       return;
434     }
435 
436     auto csis_api = CsisClient::Get();
437     if (!csis_api) {
438       bluetooth::log::warn("Csis module is not available");
439       callbacks_->OnVolumeStateChanged(device->address, device->volume, device->mute, device->flags,
440                                        true);
441       return;
442     }
443 
444     auto group_id =
445             csis_api->GetGroupId(device->address, bluetooth::le_audio::uuid::kCapServiceUuid);
446     if (group_id == bluetooth::groups::kGroupUnknown) {
447       bluetooth::log::warn("No group for device {}", device->address);
448       callbacks_->OnVolumeStateChanged(device->address, device->volume, device->mute, device->flags,
449                                        true);
450       return;
451     }
452 
453     auto devices = csis_api->GetDeviceList(group_id);
454     for (auto it = devices.begin(); it != devices.end();) {
455       auto dev = volume_control_devices_.FindByAddress(*it);
456       if (!dev || !dev->IsConnected() || (dev->address == device->address)) {
457         it = devices.erase(it);
458       } else {
459         it++;
460       }
461     }
462 
463     if (devices.empty() && (is_volume_change || is_mute_change)) {
464       bluetooth::log::info("No more devices in the group right now");
465       callbacks_->OnGroupVolumeStateChanged(group_id, device->volume, device->mute, true);
466       return;
467     }
468 
469     if (is_volume_change) {
470       std::vector<uint8_t> arg({device->volume});
471       PrepareVolumeControlOperation(devices, group_id, true, kControlPointOpcodeSetAbsoluteVolume,
472                                     arg);
473     }
474 
475     if (is_mute_change) {
476       std::vector<uint8_t> arg;
477       uint8_t opcode = device->mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute;
478       PrepareVolumeControlOperation(devices, group_id, true, opcode, arg);
479     }
480 
481     StartQueueOperation();
482   }
483 
OnVolumeControlStateReadOrNotified(VolumeControlDevice * device,uint16_t len,uint8_t * value,bool is_notification)484   void OnVolumeControlStateReadOrNotified(VolumeControlDevice* device, uint16_t len, uint8_t* value,
485                                           bool is_notification) {
486     if (len != 3) {
487       bluetooth::log::error("{}, malformed len={:#x}", device->address, len);
488       return;
489     }
490 
491     uint8_t vol;
492     uint8_t mute;
493     uint8_t* pp = value;
494     STREAM_TO_UINT8(vol, pp);
495     STREAM_TO_UINT8(mute, pp);
496     STREAM_TO_UINT8(device->change_counter, pp);
497 
498     bool is_volume_change = (device->volume != vol);
499     device->volume = vol;
500 
501     bool is_mute_change = (device->mute != mute);
502     device->mute = mute;
503 
504     bluetooth::log::info("{}, volume {:#x} mute {:#x} change_counter {:#x}", device->address,
505                          device->volume, device->mute, device->change_counter);
506 
507     if (!device->IsReady()) {
508       bluetooth::log::info("Device: {} is not ready yet.", device->address);
509       return;
510     }
511 
512     /* This is just a read, send single notification */
513     if (!is_notification) {
514       callbacks_->OnVolumeStateChanged(device->address, device->volume, device->mute, device->flags,
515                                        false);
516       return;
517     }
518 
519     auto addr = device->address;
520     auto op = find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
521                       [addr](auto& operation) {
522                         auto it = find(operation.devices_.begin(), operation.devices_.end(), addr);
523                         return it != operation.devices_.end();
524                       });
525     if (op == ongoing_operations_.end()) {
526       bluetooth::log::debug("Could not find operation id for device: {}. Autonomus change",
527                             device->address);
528       HandleAutonomusVolumeChange(device, is_volume_change, is_mute_change);
529       return;
530     }
531 
532     /* Received notification from the device we do expect */
533     auto it = find(op->devices_.begin(), op->devices_.end(), device->address);
534     op->devices_.erase(it);
535     if (!op->devices_.empty()) {
536       bluetooth::log::debug("wait for more responses for operation_id: {}", op->operation_id_);
537       return;
538     }
539 
540     if (op->IsGroupOperation()) {
541       callbacks_->OnGroupVolumeStateChanged(op->group_id_, device->volume, device->mute,
542                                             op->is_autonomous_);
543     } else {
544       /* op->is_autonomous_ will always be false,
545          since we only make it true for group operations */
546       callbacks_->OnVolumeStateChanged(device->address, device->volume, device->mute, device->flags,
547                                        false);
548     }
549 
550     ongoing_operations_.erase(op);
551     StartQueueOperation();
552   }
553 
OnVolumeControlFlagsChanged(VolumeControlDevice * device,uint16_t,uint8_t * value)554   void OnVolumeControlFlagsChanged(VolumeControlDevice* device, uint16_t /*len*/, uint8_t* value) {
555     device->flags = *value;
556 
557     bluetooth::log::info("{}, flags {:#x}", device->address, device->flags);
558   }
559 
OnExtAudioOutStateChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)560   void OnExtAudioOutStateChanged(VolumeControlDevice* device, VolumeOffset* offset, uint16_t len,
561                                  uint8_t* value) {
562     if (len != 3) {
563       bluetooth::log::error("{}, id={:#x}, malformed len={:#x}", device->address, offset->id, len);
564       return;
565     }
566 
567     uint8_t* pp = value;
568     STREAM_TO_UINT16(offset->offset, pp);
569     STREAM_TO_UINT8(offset->change_counter, pp);
570 
571     bluetooth::log::verbose("{}, len:{}", device->address, base::HexEncode(value, len));
572     bluetooth::log::info("{} id={:#x} offset: {:#x} counter: {:#x}", device->address, offset->id,
573                          offset->offset, offset->change_counter);
574 
575     if (!device->IsReady()) {
576       bluetooth::log::info("Device: {} is not ready yet.", device->address);
577       return;
578     }
579 
580     callbacks_->OnExtAudioOutVolumeOffsetChanged(device->address, offset->id, offset->offset);
581   }
582 
OnExtAudioOutLocationChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)583   void OnExtAudioOutLocationChanged(VolumeControlDevice* device, VolumeOffset* offset, uint16_t len,
584                                     uint8_t* value) {
585     if (len != 4) {
586       bluetooth::log::error("{}, id={:#x}, malformed len={:#x}", device->address, offset->id, len);
587       return;
588     }
589 
590     uint8_t* pp = value;
591     STREAM_TO_UINT32(offset->location, pp);
592 
593     bluetooth::log::verbose("{}, data :{}", device->address, base::HexEncode(value, len));
594     bluetooth::log::info("{} id={:#x}, location={:#x}", device->address, offset->id,
595                          offset->location);
596 
597     if (!device->IsReady()) {
598       bluetooth::log::info("Device: {} is not ready yet.", device->address);
599       return;
600     }
601 
602     callbacks_->OnExtAudioOutLocationChanged(device->address, offset->id, offset->location);
603   }
604 
OnExtAudioInputStateChanged(VolumeControlDevice * device,VolumeAudioInput * input,uint16_t len,uint8_t * value)605   void OnExtAudioInputStateChanged(VolumeControlDevice* device, VolumeAudioInput* input,
606                                    uint16_t len, uint8_t* value) {
607     if (len != 4) {
608       bluetooth::log::error("{}, id={}, malformed len={:#x}", device->address, input->id, len);
609       return;
610     }
611 
612     uint8_t* pp = value;
613     STREAM_TO_INT8(input->gain_setting, pp);
614     uint8_t mute;
615     STREAM_TO_UINT8(mute, pp);
616     if (!bluetooth::aics::isValidAudioInputMuteValue(mute)) {
617       bluetooth::log::error("{} Invalid mute value: {:#x}", device->address, mute);
618       return;
619     }
620     input->mute = bluetooth::aics::parseMuteField(mute);
621 
622     uint8_t gain_mode;
623     STREAM_TO_UINT8(gain_mode, pp);
624     if (!bluetooth::aics::isValidAudioInputGainModeValue(gain_mode)) {
625       bluetooth::log::error("{} Invalid GainMode value: {:#x}", device->address, gain_mode);
626       return;
627     }
628     input->gain_mode = bluetooth::aics::parseGainModeField(gain_mode);
629     STREAM_TO_UINT8(input->change_counter, pp);
630 
631     bluetooth::log::verbose("{}, data:{}", device->address, base::HexEncode(value, len));
632     bluetooth::log::info(
633             "{} id={:#x}gain_setting {:#x}, mute: {:#x}, mode: {:#x}, change_counter: {}",
634             device->address, input->id, input->gain_setting, input->mute, input->gain_mode,
635             input->change_counter);
636 
637     if (!device->device_ready) {
638       return;
639     }
640 
641     callbacks_->OnExtAudioInStateChanged(device->address, input->id, input->gain_setting,
642                                          input->mute, input->gain_mode);
643   }
644 
OnExtAudioInTypeChanged(VolumeControlDevice * device,VolumeAudioInput * input,uint16_t len,uint8_t * value)645   void OnExtAudioInTypeChanged(VolumeControlDevice* device, VolumeAudioInput* input, uint16_t len,
646                                uint8_t* value) {
647     if (len != 1) {
648       bluetooth::log::error("{}, id={}, malformed len={:#x}", device->address, input->id, len);
649       return;
650     }
651 
652     if (*value >= static_cast<uint8_t>(VolumeInputType::RFU)) {
653       bluetooth::log::error("Invalid type {} for {} id={}", device->address, *value, input->id);
654       return;
655     }
656 
657     input->type = static_cast<VolumeInputType>(*value);
658 
659     bluetooth::log::info("{}, id={:#x} type={}", device->address, input->id, input->type);
660 
661     if (!device->device_ready) {
662       return;
663     }
664 
665     callbacks_->OnExtAudioInTypeChanged(device->address, input->id, input->type);
666   }
667 
OnExtAudioInputStatusChanged(VolumeControlDevice * device,VolumeAudioInput * input,uint16_t len,uint8_t * value)668   void OnExtAudioInputStatusChanged(VolumeControlDevice* device, VolumeAudioInput* input,
669                                     uint16_t len, uint8_t* value) {
670     if (len != 1) {
671       bluetooth::log::error("{}, id={}, malformed len={:#x}", device->address, input->id, len);
672       return;
673     }
674 
675     if (*value >= static_cast<uint8_t>(VolumeInputStatus::RFU)) {
676       bluetooth::log::error("Invalid status {:#x} received from {} on id={:#x}", *value,
677                             device->address, input->id);
678       return;
679     }
680 
681     input->status = static_cast<VolumeInputStatus>(*value);
682 
683     bluetooth::log::info("{}, id={:#x} status {}", device->address, input->id, input->status);
684 
685     if (!device->device_ready) {
686       return;
687     }
688 
689     callbacks_->OnExtAudioInStatusChanged(device->address, input->id, input->status);
690   }
691 
OnExtAudioInDescChanged(VolumeControlDevice * device,VolumeAudioInput * input,uint16_t len,uint8_t * value)692   void OnExtAudioInDescChanged(VolumeControlDevice* device, VolumeAudioInput* input, uint16_t len,
693                                uint8_t* value) {
694     std::string description = std::string(value, value + len);
695     if (!base::IsStringUTF8(description)) {
696       bluetooth::log::error("Received description is no utf8 string for {}, input id={:#x}",
697                             device->address, input->id);
698     } else {
699       input->description = description;
700     }
701 
702     bluetooth::log::info("{}, id={:#x}, descriptor: {}", device->address, input->id,
703                          input->description);
704 
705     if (!device->device_ready) {
706       return;
707     }
708 
709     callbacks_->OnExtAudioInDescriptionChanged(device->address, input->id, input->description,
710                                                input->description_writable);
711   }
712 
OnExtAudioInCPWrite(uint16_t connection_id,tGATT_STATUS status,uint16_t handle,uint8_t opcode,uint8_t id)713   void OnExtAudioInCPWrite(uint16_t connection_id, tGATT_STATUS status, uint16_t handle,
714                            uint8_t opcode, uint8_t id) {
715     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
716     if (!device) {
717       bluetooth::log::info("Skipping unknown device disconnect, connection_id={:#x}",
718                            connection_id);
719       return;
720     }
721 
722     bluetooth::log::info("{}, Input Control Point write response handle {:#x}, status {:#x}",
723                          device->address, handle, status);
724     if (status == GATT_SUCCESS) {
725       return;
726     }
727 
728     switch (opcode) {
729       case kVolumeInputControlPointOpcodeSetGain:
730         callbacks_->OnExtAudioInSetGainSettingFailed(device->address, id);
731         break;
732       case kVolumeInputControlPointOpcodeMute:
733       case kVolumeInputControlPointOpcodeUnmute:
734         callbacks_->OnExtAudioInSetMuteFailed(device->address, id);
735         break;
736       case kVolumeInputControlPointOpcodeSetAutoGainMode:
737       case kVolumeInputControlPointOpcodeSetManualGainMode:
738         callbacks_->OnExtAudioInSetGainModeFailed(device->address, id);
739         break;
740       default:
741         bluetooth::log::error("{} Not a valid opcode", opcode);
742     }
743   }
744 
OnExtAudioInGainSettingChanged(VolumeControlDevice * device,VolumeAudioInput * input,uint16_t len,uint8_t * value)745   void OnExtAudioInGainSettingChanged(VolumeControlDevice* device, VolumeAudioInput* input,
746                                       uint16_t len, uint8_t* value) {
747     if (len != 3) {
748       bluetooth::log::error("{}, id={}, malformed len={:#x}", device->address, input->id, len);
749       return;
750     }
751 
752     uint8_t* pp = value;
753     STREAM_TO_UINT8(input->gain_settings.unit, pp);
754     STREAM_TO_INT8(input->gain_settings.min, pp);
755     STREAM_TO_INT8(input->gain_settings.max, pp);
756 
757     bluetooth::log::verbose("{}, len:{}", device->address, base::HexEncode(value, len));
758     bluetooth::log::info("{}, id={:#x} gain unit {:#x} gain min {:#x} gain max {:#x}",
759                          device->address, input->id, input->gain_settings.unit,
760                          input->gain_settings.min, input->gain_settings.max);
761 
762     if (!device->device_ready) {
763       return;
764     }
765 
766     callbacks_->OnExtAudioInGainSettingPropertiesChanged(
767             device->address, input->id, input->gain_settings.unit, input->gain_settings.min,
768             input->gain_settings.max);
769   }
770 
OnExtAudioOutCPWrite(tCONN_ID connection_id,tGATT_STATUS status,uint16_t handle,void *)771   void OnExtAudioOutCPWrite(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle,
772                             void* /*data*/) {
773     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
774     if (!device) {
775       bluetooth::log::error("Skipping unknown device disconnect, connection_id={:#x}",
776                             connection_id);
777       return;
778     }
779 
780     bluetooth::log::info("Offset Control Point write response handle{:#x} status: {:#x}", handle,
781                          static_cast<int>(status));
782 
783     /* TODO Design callback API to notify about changes */
784   }
785 
OnOffsetOutputDescChanged(VolumeControlDevice * device,VolumeOffset * offset,uint16_t len,uint8_t * value)786   void OnOffsetOutputDescChanged(VolumeControlDevice* device, VolumeOffset* offset, uint16_t len,
787                                  uint8_t* value) {
788     std::string description = std::string(value, value + len);
789     if (!base::IsStringUTF8(description)) {
790       bluetooth::log::error(" Received description is no utf8 string for {}, offset id={:#x}",
791                             device->address, offset->id);
792     } else {
793       offset->description = description;
794     }
795 
796     bluetooth::log::info("{}, {}", device->address, description);
797 
798     if (!device->IsReady()) {
799       bluetooth::log::info("Device: {} is not ready yet.", device->address);
800       return;
801     }
802 
803     callbacks_->OnExtAudioOutDescriptionChanged(device->address, offset->id, offset->description);
804   }
805 
OnGattWriteCcc(tCONN_ID connection_id,tGATT_STATUS status,uint16_t handle,uint16_t,const uint8_t *,void *)806   void OnGattWriteCcc(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle,
807                       uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {
808     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
809     if (!device) {
810       bluetooth::log::error("unknown connection_id={:#x}", connection_id);
811       BtaGattQueue::Clean(connection_id);
812       return;
813     }
814 
815     if (status != GATT_SUCCESS) {
816       if (status == GATT_DATABASE_OUT_OF_SYNC) {
817         bluetooth::log::info("Database out of sync for {}, conn_id: 0x{:04x}", device->address,
818                              connection_id);
819         ClearDeviceInformationAndStartSearch(device);
820       } else {
821         bluetooth::log::error("Failed to register for notification: 0x{:04x}, status 0x{:02x}",
822                               handle, status);
823         device_cleanup_helper(device, true);
824       }
825       return;
826     }
827 
828     bluetooth::log::info("Successfully registered on ccc: 0x{:04x}, device: {}", handle,
829                          device->address);
830 
831     verify_device_ready(device, handle);
832   }
833 
OnGattWriteCccStatic(tCONN_ID connection_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)834   static void OnGattWriteCccStatic(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle,
835                                    uint16_t len, const uint8_t* value, void* data) {
836     if (!instance) {
837       bluetooth::log::error("connection_id={:#x}, no instance. Handle to write={:#x}",
838                             connection_id, handle);
839       return;
840     }
841 
842     instance->OnGattWriteCcc(connection_id, status, handle, len, value, data);
843   }
844 
Dump(int fd)845   void Dump(int fd) {
846     dprintf(fd, "APP ID: %d\n", gatt_if_);
847     volume_control_devices_.DebugDump(fd);
848   }
849 
Disconnect(const RawAddress & address)850   void Disconnect(const RawAddress& address) override {
851     bluetooth::log::info("{}", address);
852 
853     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
854     if (!device) {
855       bluetooth::log::warn("Device not connected to profile {}", address);
856       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
857       return;
858     }
859 
860     bluetooth::log::info("GAP_EVT_CONN_CLOSED: {}", device->address);
861     device->connecting_actively = false;
862     device_cleanup_helper(device, true);
863   }
864 
Remove(const RawAddress & address)865   void Remove(const RawAddress& address) override {
866     bluetooth::log::info("{}", address);
867 
868     /* Removes all registrations for connection. */
869     BTA_GATTC_CancelOpen(gatt_if_, address, true);
870 
871     Disconnect(address);
872     volume_control_devices_.Remove(address);
873   }
874 
OnGattDisconnected(tCONN_ID connection_id,tGATT_IF,RawAddress remote_bda,tGATT_DISCONN_REASON)875   void OnGattDisconnected(tCONN_ID connection_id, tGATT_IF /*client_if*/, RawAddress remote_bda,
876                           tGATT_DISCONN_REASON /*reason*/) {
877     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
878     if (!device) {
879       bluetooth::log::error("Skipping unknown device disconnect, connection_id={:#x}",
880                             connection_id);
881       return;
882     }
883 
884     if (!device->IsConnected()) {
885       bluetooth::log::error(
886               "Skipping disconnect of the already disconnected device, "
887               "connection_id={:#x}",
888               connection_id);
889       return;
890     }
891 
892     bluetooth::log::info("{}", remote_bda);
893 
894     bool notify = device->IsReady() || device->connecting_actively;
895     device_cleanup_helper(device, notify);
896 
897     StartOpportunisticConnect(remote_bda);
898   }
899 
RemoveDeviceFromOperationList(const RawAddress & addr)900   void RemoveDeviceFromOperationList(const RawAddress& addr) {
901     if (ongoing_operations_.empty()) {
902       return;
903     }
904 
905     for (auto& op : ongoing_operations_) {
906       auto it = find(op.devices_.begin(), op.devices_.end(), addr);
907       if (it == op.devices_.end()) {
908         continue;
909       }
910       op.devices_.erase(it);
911     }
912 
913     // Remove operations with no devices
914     auto it = ongoing_operations_.begin();
915     while (it != ongoing_operations_.end()) {
916       if (it->devices_.empty()) {
917         it = ongoing_operations_.erase(it);
918       } else {
919         ++it;
920       }
921     }
922   }
923 
RemoveDeviceFromOperationList(const RawAddress & addr,int operation_id)924   void RemoveDeviceFromOperationList(const RawAddress& addr, int operation_id) {
925     auto op = find_if(
926             ongoing_operations_.begin(), ongoing_operations_.end(),
927             [operation_id](auto& operation) { return operation.operation_id_ == operation_id; });
928 
929     if (op == ongoing_operations_.end()) {
930       bluetooth::log::warn("Could not find operation id: {}", operation_id);
931       return;
932     }
933 
934     auto it = find(op->devices_.begin(), op->devices_.end(), addr);
935     if (it != op->devices_.end()) {
936       op->devices_.erase(it);
937       if (op->devices_.empty()) {
938         ongoing_operations_.erase(op);
939         StartQueueOperation();
940       }
941       return;
942     }
943   }
944 
IsMuteOrUnmuteRequired(VolumeControlDevice * dev,bool mute)945   bool IsMuteOrUnmuteRequired(VolumeControlDevice* dev, bool mute) {
946     if (!dev->IsReady()) {
947       return false;
948     }
949 
950     // Check if the mute status differs on the remote
951     if (dev->mute != mute) {
952       return true;
953     }
954 
955     // Check if the mute status differs in the currently executing request
956     uint8_t oppositeOpcode = mute ? kControlPointOpcodeUnmute : kControlPointOpcodeMute;
957     const auto op = &ongoing_operations_.front();
958     if (op->IsStarted() && (op->opcode_ == oppositeOpcode) &&
959         (std::find(op->devices_.begin(), op->devices_.end(), dev->address) != op->devices_.end())) {
960       return true;
961     }
962 
963     return false;
964   }
965 
IsSetAbsoluteVolumeRequired(VolumeControlDevice * dev,uint8_t volume)966   bool IsSetAbsoluteVolumeRequired(VolumeControlDevice* dev, uint8_t volume) {
967     if (!dev->IsReady()) {
968       return false;
969     }
970 
971     // Check if the volume differs on the remote
972     if (dev->volume != volume) {
973       return true;
974     }
975 
976     // Check if the volume differs in the currently executing request
977     const auto op = &ongoing_operations_.front();
978     std::vector<uint8_t> arg({volume});
979     if (op->IsStarted() && (op->opcode_ == kControlPointOpcodeSetAbsoluteVolume) &&
980         (std::find(op->devices_.begin(), op->devices_.end(), dev->address) != op->devices_.end()) &&
981         !std::equal(op->arguments_.begin(), op->arguments_.end(), arg.begin())) {
982       return true;
983     }
984 
985     return false;
986   }
987 
RemoveNotStartedPendingOperations(const std::vector<RawAddress> & devices,int group_id,std::vector<uint8_t> opcodes)988   void RemoveNotStartedPendingOperations(const std::vector<RawAddress>& devices, int group_id,
989                                          std::vector<uint8_t> opcodes) {
990     bluetooth::log::debug("");
991     for (auto op = ongoing_operations_.begin(); op != ongoing_operations_.end();) {
992       if (op->IsStarted() || (!opcodes.empty() && std::find(opcodes.begin(), opcodes.end(),
993                                                             op->opcode_) == opcodes.end())) {
994         op++;
995         continue;
996       }
997       if (group_id != bluetooth::groups::kGroupUnknown && op->group_id_ == group_id) {
998         bluetooth::log::debug("Removing operation {}", op->operation_id_);
999         op = ongoing_operations_.erase(op);
1000         continue;
1001       }
1002       for (auto const& addr : devices) {
1003         auto it = find(op->devices_.begin(), op->devices_.end(), addr);
1004         if (it != op->devices_.end()) {
1005           bluetooth::log::debug("Removing {} from operation", *it);
1006           op->devices_.erase(it);
1007         }
1008       }
1009       if (op->devices_.empty()) {
1010         bluetooth::log::debug("Removing operation {}", op->operation_id_);
1011         op = ongoing_operations_.erase(op);
1012       } else {
1013         op++;
1014       }
1015     }
1016   }
1017 
OnWriteControlResponse(tCONN_ID connection_id,tGATT_STATUS status,uint16_t handle,void * data)1018   void OnWriteControlResponse(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle,
1019                               void* data) {
1020     VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id);
1021     if (!device) {
1022       bluetooth::log::error("Skipping unknown device disconnect, connection_id={:#x}",
1023                             connection_id);
1024       return;
1025     }
1026 
1027     bluetooth::log::info("Write response handle: {:#x} status: {:#x}", handle,
1028                          static_cast<int>(status));
1029 
1030     if (status == GATT_SUCCESS) {
1031       return;
1032     }
1033 
1034     /* In case of error, remove device from the tracking operation list */
1035     RemoveDeviceFromOperationList(device->address, PTR_TO_INT(data));
1036 
1037     if (status == GATT_DATABASE_OUT_OF_SYNC) {
1038       bluetooth::log::info("Database out of sync for {}", device->address);
1039       ClearDeviceInformationAndStartSearch(device);
1040     }
1041   }
1042 
operation_timeout_callback(void * data)1043   static void operation_timeout_callback(void* data) {
1044     if (!instance) {
1045       bluetooth::log::warn("There is no instance.");
1046       return;
1047     }
1048     instance->OperationMonitorTimeoutFired(PTR_TO_INT(data));
1049   }
1050 
OperationMonitorTimeoutFired(int operation_id)1051   void OperationMonitorTimeoutFired(int operation_id) {
1052     auto op = find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
1053                       [operation_id](auto& it) { return it.operation_id_ == operation_id; });
1054 
1055     if (op == ongoing_operations_.end()) {
1056       bluetooth::log::error("Could not find operation_id: {}", operation_id);
1057       return;
1058     }
1059 
1060     bluetooth::log::warn("Operation {} is taking too long for devices:", operation_id);
1061     for (const auto& addr : op->devices_) {
1062       bluetooth::log::warn("{},", addr);
1063     }
1064     alarm_set_on_mloop(op->operation_timeout_, kOperationMonitorTimeoutMs,
1065                        operation_timeout_callback, INT_TO_PTR(operation_id));
1066   }
1067 
StartQueueOperation(void)1068   void StartQueueOperation(void) {
1069     bluetooth::log::info("");
1070     if (ongoing_operations_.empty()) {
1071       return;
1072     }
1073 
1074     auto op = &ongoing_operations_.front();
1075 
1076     bluetooth::log::info("Current operation_id: {}", op->operation_id_);
1077 
1078     if (op->IsStarted()) {
1079       bluetooth::log::info("Operation {} is started, wait until it is complete", op->operation_id_);
1080       return;
1081     }
1082 
1083     op->Start();
1084 
1085     alarm_set_on_mloop(op->operation_timeout_, kOperationMonitorTimeoutMs,
1086                        operation_timeout_callback, INT_TO_PTR(op->operation_id_));
1087     devices_control_point_helper(op->devices_, op->opcode_,
1088                                  op->arguments_.size() == 0 ? nullptr : &(op->arguments_),
1089                                  op->operation_id_);
1090   }
1091 
PrepareVolumeControlOperation(std::vector<RawAddress> devices,int group_id,bool is_autonomous,uint8_t opcode,const std::vector<uint8_t> & arguments)1092   void PrepareVolumeControlOperation(std::vector<RawAddress> devices, int group_id,
1093                                      bool is_autonomous, uint8_t opcode,
1094                                      const std::vector<uint8_t>& arguments) {
1095     bluetooth::log::debug(
1096             "num of devices: {}, group_id: {}, is_autonomous: {}  opcode: {}, arg "
1097             "size: {}",
1098             devices.size(), group_id, is_autonomous, opcode, arguments.size());
1099 
1100     if (std::find_if(
1101                 ongoing_operations_.begin(), ongoing_operations_.end(),
1102                 [opcode, &devices, &arguments](const VolumeOperation& op) {
1103                   if (op.opcode_ != opcode) {
1104                     return false;
1105                   }
1106                   if (!std::equal(op.arguments_.begin(), op.arguments_.end(), arguments.begin())) {
1107                     return false;
1108                   }
1109                   // Filter out all devices which have the exact operation
1110                   // already scheduled
1111                   devices.erase(std::remove_if(devices.begin(), devices.end(),
1112                                                [&op](auto d) {
1113                                                  return find(op.devices_.begin(), op.devices_.end(),
1114                                                              d) != op.devices_.end();
1115                                                }),
1116                                 devices.end());
1117                   return devices.empty();
1118                 }) == ongoing_operations_.end()) {
1119       bluetooth::log::debug("New operation id {} added", latest_operation_id_);
1120       ongoing_operations_.emplace_back(latest_operation_id_++, group_id, is_autonomous, opcode,
1121                                        arguments, devices);
1122     }
1123   }
1124 
MuteUnmute(std::variant<RawAddress,int> addr_or_group_id,bool mute)1125   void MuteUnmute(std::variant<RawAddress, int> addr_or_group_id, bool mute) {
1126     std::vector<uint8_t> arg;
1127 
1128     uint8_t opcode = mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute;
1129 
1130     if (std::holds_alternative<RawAddress>(addr_or_group_id)) {
1131       VolumeControlDevice* dev =
1132               volume_control_devices_.FindByAddress(std::get<RawAddress>(addr_or_group_id));
1133       if (dev != nullptr) {
1134         bluetooth::log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady());
1135         std::vector<RawAddress> devices = {dev->address};
1136         if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1137           if (dev->IsReady() && (dev->mute != mute)) {
1138             PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode,
1139                                           arg);
1140           }
1141         } else {
1142           RemoveNotStartedPendingOperations(devices, bluetooth::groups::kGroupUnknown,
1143                                             {kControlPointOpcodeMute, kControlPointOpcodeUnmute});
1144           if (IsMuteOrUnmuteRequired(dev, mute)) {
1145             PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode,
1146                                           arg);
1147           }
1148         }
1149       }
1150     } else {
1151       /* Handle group change */
1152       auto group_id = std::get<int>(addr_or_group_id);
1153       bluetooth::log::debug("group: {}", group_id);
1154       auto csis_api = CsisClient::Get();
1155       if (!csis_api) {
1156         bluetooth::log::error("Csis is not there");
1157         return;
1158       }
1159 
1160       auto devices = csis_api->GetDeviceList(group_id);
1161       if (devices.empty()) {
1162         bluetooth::log::error("group id: {} has no devices", group_id);
1163         return;
1164       }
1165 
1166       if (com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1167         RemoveNotStartedPendingOperations(devices, group_id,
1168                                           {kControlPointOpcodeMute, kControlPointOpcodeUnmute});
1169       }
1170 
1171       bool muteNotChanged = false;
1172       bool deviceNotReady = false;
1173 
1174       for (auto it = devices.begin(); it != devices.end();) {
1175         auto dev = volume_control_devices_.FindByAddress(*it);
1176         if (!dev) {
1177           it = devices.erase(it);
1178           continue;
1179         }
1180 
1181         if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1182           if (!dev->IsReady() || (dev->mute == mute)) {
1183             it = devices.erase(it);
1184             muteNotChanged = muteNotChanged ? muteNotChanged : (dev->mute == mute);
1185             deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
1186             continue;
1187           }
1188         } else {
1189           if (!IsMuteOrUnmuteRequired(dev, mute)) {
1190             it = devices.erase(it);
1191             muteNotChanged = muteNotChanged ? muteNotChanged : (dev->mute == mute);
1192             deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
1193             continue;
1194           }
1195         }
1196         it++;
1197       }
1198 
1199       if (devices.empty()) {
1200         bluetooth::log::debug(
1201                 "No need to update mute for group id: {} . muteNotChanged: {}, "
1202                 "deviceNotReady: {}",
1203                 group_id, muteNotChanged, deviceNotReady);
1204         return;
1205       }
1206 
1207       PrepareVolumeControlOperation(devices, group_id, false, opcode, arg);
1208     }
1209 
1210     StartQueueOperation();
1211   }
1212 
Mute(std::variant<RawAddress,int> addr_or_group_id)1213   void Mute(std::variant<RawAddress, int> addr_or_group_id) override {
1214     bluetooth::log::debug("");
1215     MuteUnmute(addr_or_group_id, true /* mute */);
1216   }
1217 
UnMute(std::variant<RawAddress,int> addr_or_group_id)1218   void UnMute(std::variant<RawAddress, int> addr_or_group_id) override {
1219     bluetooth::log::debug("");
1220     MuteUnmute(addr_or_group_id, false /* mute */);
1221   }
1222 
SetVolume(std::variant<RawAddress,int> addr_or_group_id,uint8_t volume)1223   void SetVolume(std::variant<RawAddress, int> addr_or_group_id, uint8_t volume) override {
1224     std::vector<uint8_t> arg({volume});
1225     uint8_t opcode = kControlPointOpcodeSetAbsoluteVolume;
1226 
1227     if (std::holds_alternative<RawAddress>(addr_or_group_id)) {
1228       bluetooth::log::debug("Address: {}:", std::get<RawAddress>(addr_or_group_id));
1229       VolumeControlDevice* dev =
1230               volume_control_devices_.FindByAddress(std::get<RawAddress>(addr_or_group_id));
1231       if (dev != nullptr) {
1232         bluetooth::log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady());
1233         std::vector<RawAddress> devices = {dev->address};
1234         if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1235           if (dev->IsReady() && (dev->volume != volume)) {
1236             RemoveNotStartedPendingOperations(
1237                     devices, bluetooth::groups::kGroupUnknown,
1238                     {kControlPointOpcodeVolumeDown, kControlPointOpcodeVolumeUp,
1239                      kControlPointOpcodeSetAbsoluteVolume});
1240             PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode,
1241                                           arg);
1242           }
1243         } else {
1244           RemoveNotStartedPendingOperations(
1245                   devices, bluetooth::groups::kGroupUnknown,
1246                   {kControlPointOpcodeVolumeDown, kControlPointOpcodeVolumeUp,
1247                    kControlPointOpcodeSetAbsoluteVolume});
1248           if (IsSetAbsoluteVolumeRequired(dev, volume)) {
1249             PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode,
1250                                           arg);
1251           }
1252         }
1253       }
1254     } else {
1255       /* Handle group change */
1256       auto group_id = std::get<int>(addr_or_group_id);
1257       bluetooth::log::debug("group_id: {}, vol: {}", group_id, volume);
1258       auto csis_api = CsisClient::Get();
1259       if (!csis_api) {
1260         bluetooth::log::error("Csis is not there");
1261         return;
1262       }
1263 
1264       auto devices = csis_api->GetDeviceList(group_id);
1265       if (devices.empty()) {
1266         bluetooth::log::error("group id: {} has no devices", group_id);
1267         return;
1268       }
1269 
1270       if (com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1271         RemoveNotStartedPendingOperations(
1272                 devices, group_id,
1273                 {kControlPointOpcodeVolumeDown, kControlPointOpcodeVolumeUp,
1274                  kControlPointOpcodeSetAbsoluteVolume});
1275       }
1276 
1277       bool volumeNotChanged = false;
1278       bool deviceNotReady = false;
1279 
1280       for (auto it = devices.begin(); it != devices.end();) {
1281         auto dev = volume_control_devices_.FindByAddress(*it);
1282         if (!dev) {
1283           it = devices.erase(it);
1284           continue;
1285         }
1286 
1287         if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1288           if (!dev->IsReady() || (dev->volume == volume)) {
1289             it = devices.erase(it);
1290             volumeNotChanged = volumeNotChanged ? volumeNotChanged : (dev->volume == volume);
1291             deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
1292             continue;
1293           }
1294         } else {
1295           if (!IsSetAbsoluteVolumeRequired(dev, volume)) {
1296             it = devices.erase(it);
1297             volumeNotChanged = volumeNotChanged ? volumeNotChanged : (dev->volume == volume);
1298             deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
1299             continue;
1300           }
1301         }
1302 
1303         it++;
1304       }
1305 
1306       if (devices.empty()) {
1307         bluetooth::log::debug(
1308                 "No need to update volume for group id: {} . volumeNotChanged: {}, "
1309                 "deviceNotReady: {}",
1310                 group_id, volumeNotChanged, deviceNotReady);
1311         return;
1312       }
1313 
1314       if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
1315         RemoveNotStartedPendingOperations(
1316                 devices, group_id,
1317                 {kControlPointOpcodeVolumeDown, kControlPointOpcodeVolumeUp,
1318                  kControlPointOpcodeSetAbsoluteVolume});
1319       }
1320       PrepareVolumeControlOperation(devices, group_id, false, opcode, arg);
1321     }
1322 
1323     StartQueueOperation();
1324   }
1325 
1326   /* Methods to operate on Volume Control Offset Service (VOCS) */
GetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id)1327   void GetExtAudioOutVolumeOffset(const RawAddress& address, uint8_t ext_output_id) override {
1328     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1329     if (!device) {
1330       bluetooth::log::error("no such device!");
1331       return;
1332     }
1333 
1334     device->GetExtAudioOutVolumeOffset(ext_output_id, chrc_read_callback_static, nullptr);
1335   }
1336 
SetExtAudioOutVolumeOffset(const RawAddress & address,uint8_t ext_output_id,int16_t offset_val)1337   void SetExtAudioOutVolumeOffset(const RawAddress& address, uint8_t ext_output_id,
1338                                   int16_t offset_val) override {
1339     std::vector<uint8_t> arg(2);
1340     uint8_t* ptr = arg.data();
1341     UINT16_TO_STREAM(ptr, offset_val);
1342     ext_audio_out_control_point_helper(address, ext_output_id, kVolumeOffsetControlPointOpcodeSet,
1343                                        &arg);
1344   }
1345 
GetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id)1346   void GetExtAudioOutLocation(const RawAddress& address, uint8_t ext_output_id) override {
1347     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1348     if (!device) {
1349       bluetooth::log::error("no such device!");
1350       return;
1351     }
1352 
1353     device->GetExtAudioOutLocation(ext_output_id, chrc_read_callback_static, nullptr);
1354   }
1355 
SetExtAudioOutLocation(const RawAddress & address,uint8_t ext_output_id,uint32_t location)1356   void SetExtAudioOutLocation(const RawAddress& address, uint8_t ext_output_id,
1357                               uint32_t location) override {
1358     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1359     if (!device) {
1360       bluetooth::log::error("no such device!");
1361       return;
1362     }
1363 
1364     device->SetExtAudioOutLocation(ext_output_id, location);
1365   }
1366 
GetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id)1367   void GetExtAudioOutDescription(const RawAddress& address, uint8_t ext_output_id) override {
1368     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1369     if (!device) {
1370       bluetooth::log::error("no such device!");
1371       return;
1372     }
1373 
1374     device->GetExtAudioOutDescription(ext_output_id, chrc_read_callback_static, nullptr);
1375   }
1376 
SetExtAudioOutDescription(const RawAddress & address,uint8_t ext_output_id,std::string descr)1377   void SetExtAudioOutDescription(const RawAddress& address, uint8_t ext_output_id,
1378                                  std::string descr) override {
1379     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1380     if (!device) {
1381       bluetooth::log::error("no such device!");
1382       return;
1383     }
1384 
1385     device->SetExtAudioOutDescription(ext_output_id, descr);
1386   }
1387 
1388   /* Methods to operate on Audio Input Service (AIS) */
GetExtAudioInState(const RawAddress & address,uint8_t ext_input_id)1389   void GetExtAudioInState(const RawAddress& address, uint8_t ext_input_id) override {
1390     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1391     if (!device) {
1392       bluetooth::log::error("{}, no such device!", address);
1393       return;
1394     }
1395 
1396     device->GetExtAudioInState(ext_input_id, chrc_read_callback_static, nullptr);
1397   }
1398 
GetExtAudioInStatus(const RawAddress & address,uint8_t ext_input_id)1399   void GetExtAudioInStatus(const RawAddress& address, uint8_t ext_input_id) override {
1400     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1401     if (!device) {
1402       bluetooth::log::error("{}, no such device!", address);
1403       return;
1404     }
1405 
1406     device->GetExtAudioInStatus(ext_input_id, chrc_read_callback_static, nullptr);
1407   }
1408 
GetExtAudioInType(const RawAddress & address,uint8_t ext_input_id)1409   void GetExtAudioInType(const RawAddress& address, uint8_t ext_input_id) override {
1410     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1411     if (!device) {
1412       bluetooth::log::error("{}, no such device!", address);
1413       return;
1414     }
1415 
1416     device->GetExtAudioInType(ext_input_id, chrc_read_callback_static, nullptr);
1417   }
1418 
GetExtAudioInGainProps(const RawAddress & address,uint8_t ext_input_id)1419   void GetExtAudioInGainProps(const RawAddress& address, uint8_t ext_input_id) override {
1420     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1421     if (!device) {
1422       bluetooth::log::error("{}, no such device!", address);
1423       return;
1424     }
1425 
1426     device->GetExtAudioInGainProps(ext_input_id, chrc_read_callback_static, nullptr);
1427   }
1428 
GetExtAudioInDescription(const RawAddress & address,uint8_t ext_input_id)1429   void GetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id) override {
1430     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1431     if (!device) {
1432       bluetooth::log::error("{}, no such device!", address);
1433       return;
1434     }
1435 
1436     device->GetExtAudioInDescription(ext_input_id, chrc_read_callback_static, nullptr);
1437   }
1438 
SetExtAudioInDescription(const RawAddress & address,uint8_t ext_input_id,std::string descr)1439   void SetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id,
1440                                 std::string descr) override {
1441     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1442     if (!device) {
1443       bluetooth::log::error("{}, no such device!", address);
1444       return;
1445     }
1446 
1447     device->SetExtAudioInDescription(ext_input_id, descr);
1448   }
1449 
SetExtAudioInGainSetting(const RawAddress & address,uint8_t ext_input_id,int8_t gain_setting)1450   void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id,
1451                                 int8_t gain_setting) override {
1452     std::vector<uint8_t> arg({(uint8_t)gain_setting});
1453     bluetooth::log::info("{}, input_id={:#x}", address, ext_input_id);
1454 
1455     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1456     if (!device) {
1457       bluetooth::log::error("{}, no such device!", address);
1458       callbacks_->OnExtAudioInSetGainSettingFailed(address, ext_input_id);
1459       return;
1460     }
1461 
1462     if (!device->ExtAudioInControlPointOperation(
1463                 ext_input_id, kVolumeInputControlPointOpcodeSetGain, &arg,
1464                 [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
1465                    const uint8_t* /*value*/, void* data) {
1466                   if (instance) {
1467                     instance->OnExtAudioInCPWrite(connection_id, status, handle,
1468                                                   kVolumeInputControlPointOpcodeSetGain,
1469                                                   PTR_TO_INT(data));
1470                   }
1471                 },
1472                 INT_TO_PTR(ext_input_id))) {
1473       callbacks_->OnExtAudioInSetGainSettingFailed(address, ext_input_id);
1474     }
1475   }
1476 
SetExtAudioInGainMode(const RawAddress & address,uint8_t ext_input_id,bluetooth::aics::GainMode gain_mode)1477   void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id,
1478                              bluetooth::aics::GainMode gain_mode) override {
1479     bluetooth::log::info("{}, input_id={:#x} gain_mode={:#x}", address, ext_input_id, gain_mode);
1480 
1481     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1482     if (!device) {
1483       bluetooth::log::error("{}, no such device!", address);
1484       callbacks_->OnExtAudioInSetGainModeFailed(address, ext_input_id);
1485       return;
1486     }
1487 
1488     if (!device->ExtAudioInControlPointOperation(
1489                 ext_input_id,
1490                 gain_mode == bluetooth::aics::GainMode::AUTOMATIC
1491                         ? kVolumeInputControlPointOpcodeSetAutoGainMode
1492                         : kVolumeInputControlPointOpcodeSetManualGainMode,
1493                 nullptr,
1494                 [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
1495                    const uint8_t* /*value*/, void* data) {
1496                   if (instance) {
1497                     instance->OnExtAudioInCPWrite(connection_id, status, handle,
1498                                                   kVolumeInputControlPointOpcodeSetAutoGainMode,
1499                                                   PTR_TO_INT(data));
1500                   }
1501                 },
1502                 INT_TO_PTR(ext_input_id))) {
1503       callbacks_->OnExtAudioInSetGainModeFailed(address, ext_input_id);
1504     }
1505   }
1506 
SetExtAudioInMute(const RawAddress & address,uint8_t ext_input_id,bluetooth::aics::Mute mute)1507   void SetExtAudioInMute(const RawAddress& address, uint8_t ext_input_id,
1508                          bluetooth::aics::Mute mute) override {
1509     bluetooth::log::info("{}, input_id={:#x}, mute={:#x}", address, ext_input_id, mute);
1510 
1511     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1512     if (!device) {
1513       bluetooth::log::error("{}, no such device!", address);
1514       callbacks_->OnExtAudioInSetMuteFailed(address, ext_input_id);
1515       return;
1516     }
1517 
1518     if (!device->ExtAudioInControlPointOperation(
1519                 ext_input_id,
1520                 mute == bluetooth::aics::Mute::MUTED ? kVolumeInputControlPointOpcodeMute
1521                                                      : kVolumeInputControlPointOpcodeUnmute,
1522                 nullptr,
1523                 [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
1524                    const uint8_t* /*value*/, void* data) {
1525                   if (instance) {
1526                     instance->OnExtAudioInCPWrite(connection_id, status, handle,
1527                                                   kVolumeInputControlPointOpcodeMute,
1528                                                   PTR_TO_INT(data));
1529                   }
1530                 },
1531                 INT_TO_PTR(ext_input_id))) {
1532       callbacks_->OnExtAudioInSetMuteFailed(address, ext_input_id);
1533     }
1534   }
1535 
CleanUp()1536   void CleanUp() {
1537     bluetooth::log::info("");
1538     volume_control_devices_.Disconnect(gatt_if_);
1539     volume_control_devices_.Clear();
1540     ongoing_operations_.clear();
1541     BTA_GATTC_AppDeregister(gatt_if_);
1542   }
1543 
1544 private:
1545   tGATT_IF gatt_if_;
1546   bluetooth::vc::VolumeControlCallbacks* callbacks_;
1547   VolumeControlDevices volume_control_devices_;
1548 
1549   /* Used to track volume control operations */
1550   std::list<VolumeOperation> ongoing_operations_;
1551   int latest_operation_id_;
1552 
1553   static constexpr uint64_t kOperationMonitorTimeoutMs = 3000;
1554 
verify_device_ready(VolumeControlDevice * device,uint16_t handle)1555   void verify_device_ready(VolumeControlDevice* device, uint16_t handle) {
1556     bluetooth::log::debug("{}, isReady {}", device->address, device->IsReady());
1557     if (device->IsReady()) {
1558       return;
1559     }
1560 
1561     // VerifyReady sets the device_ready flag if all remaining GATT operations
1562     // are completed
1563     if (device->VerifyReady(handle)) {
1564       bluetooth::log::info("Outstanding reads completed.");
1565 
1566       callbacks_->OnDeviceAvailable(device->address, device->audio_offsets.Size(),
1567                                     device->audio_inputs.Size());
1568       callbacks_->OnConnectionState(ConnectionState::CONNECTED, device->address);
1569 
1570       // once profile connected we can notify current states
1571       callbacks_->OnVolumeStateChanged(device->address, device->volume, device->mute, device->flags,
1572                                        true);
1573 
1574       device->EnqueueRemainingRequests(gatt_if_, chrc_read_callback_static,
1575                                        chrc_multi_read_callback_static, OnGattWriteCccStatic);
1576     }
1577   }
1578 
device_cleanup_helper(VolumeControlDevice * device,bool notify)1579   void device_cleanup_helper(VolumeControlDevice* device, bool notify) {
1580     device->Disconnect(gatt_if_);
1581 
1582     RemoveDeviceFromOperationList(device->address);
1583     device->mtu_ = GATT_DEF_BLE_MTU_SIZE;
1584 
1585     if (notify) {
1586       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, device->address);
1587     }
1588   }
1589 
devices_control_point_helper(const std::vector<RawAddress> & devices,uint8_t opcode,const std::vector<uint8_t> * arg,int operation_id=-1)1590   void devices_control_point_helper(const std::vector<RawAddress>& devices, uint8_t opcode,
1591                                     const std::vector<uint8_t>* arg, int operation_id = -1) {
1592     volume_control_devices_.ControlPointOperation(
1593             devices, opcode, arg,
1594             [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
1595                const uint8_t* /*value*/, void* data) {
1596               if (instance) {
1597                 instance->OnWriteControlResponse(connection_id, status, handle, data);
1598               }
1599             },
1600             INT_TO_PTR(operation_id));
1601   }
1602 
ext_audio_out_control_point_helper(const RawAddress & address,uint8_t ext_output_id,uint8_t opcode,const std::vector<uint8_t> * arg)1603   void ext_audio_out_control_point_helper(const RawAddress& address, uint8_t ext_output_id,
1604                                           uint8_t opcode, const std::vector<uint8_t>* arg) {
1605     bluetooth::log::info("{} id={:#x} op={:#x}", address, ext_output_id, opcode);
1606     VolumeControlDevice* device = volume_control_devices_.FindByAddress(address);
1607     if (!device) {
1608       bluetooth::log::error("no such device!");
1609       return;
1610     }
1611     device->ExtAudioOutControlPointOperation(
1612             ext_output_id, opcode, arg,
1613             [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
1614                const uint8_t* /*value*/, void* data) {
1615               if (instance) {
1616                 instance->OnExtAudioOutCPWrite(connection_id, status, handle, data);
1617               }
1618             },
1619             nullptr);
1620   }
1621 
gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1622   void gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1623     bluetooth::log::info("event = {}", static_cast<int>(event));
1624 
1625     if (p_data == nullptr) {
1626       return;
1627     }
1628 
1629     switch (event) {
1630       case BTA_GATTC_OPEN_EVT: {
1631         tBTA_GATTC_OPEN& o = p_data->open;
1632         OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda, o.transport, o.mtu);
1633       } break;
1634 
1635       case BTA_GATTC_CLOSE_EVT: {
1636         tBTA_GATTC_CLOSE& c = p_data->close;
1637         OnGattDisconnected(c.conn_id, c.client_if, c.remote_bda, c.reason);
1638       } break;
1639 
1640       case BTA_GATTC_SEARCH_CMPL_EVT:
1641         OnServiceSearchComplete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
1642         break;
1643 
1644       case BTA_GATTC_NOTIF_EVT: {
1645         tBTA_GATTC_NOTIFY& n = p_data->notify;
1646         if (!n.is_notify || n.len > GATT_MAX_ATTR_LEN) {
1647           bluetooth::log::error("rejected BTA_GATTC_NOTIF_EVT. is_notify={}, len={}", n.is_notify,
1648                                 static_cast<int>(n.len));
1649           break;
1650         }
1651         OnNotificationEvent(n.conn_id, n.handle, n.len, n.value);
1652       } break;
1653 
1654       case BTA_GATTC_ENC_CMPL_CB_EVT: {
1655         tBTM_STATUS encryption_status;
1656         if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
1657           encryption_status = tBTM_STATUS::BTM_SUCCESS;
1658         } else {
1659           encryption_status = tBTM_STATUS::BTM_FAILED_ON_SECURITY;
1660         }
1661         OnEncryptionComplete(p_data->enc_cmpl.remote_bda, encryption_status);
1662       } break;
1663 
1664       case BTA_GATTC_SRVC_CHG_EVT:
1665         OnServiceChangeEvent(p_data->service_changed.remote_bda);
1666         break;
1667 
1668       case BTA_GATTC_CFG_MTU_EVT:
1669         OnMtuChanged(p_data->cfg_mtu.conn_id, p_data->cfg_mtu.mtu);
1670         break;
1671 
1672       case BTA_GATTC_SRVC_DISC_DONE_EVT:
1673         OnServiceDiscDoneEvent(p_data->service_discovery_done.remote_bda);
1674         break;
1675 
1676       default:
1677         break;
1678     }
1679   }
1680 
gattc_callback_static(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1681   static void gattc_callback_static(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1682     if (instance) {
1683       instance->gattc_callback(event, p_data);
1684     }
1685   }
1686 
chrc_read_callback_static(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)1687   static void chrc_read_callback_static(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle,
1688                                         uint16_t len, uint8_t* value, void* data) {
1689     if (instance) {
1690       instance->OnCharacteristicValueChanged(conn_id, status, handle, len, value, data, false);
1691     }
1692   }
1693 
chrc_multi_read_callback_static(uint16_t conn_id,tGATT_STATUS status,tBTA_GATTC_MULTI & handles,uint16_t total_len,uint8_t * value,void * data)1694   static void chrc_multi_read_callback_static(uint16_t conn_id, tGATT_STATUS status,
1695                                               tBTA_GATTC_MULTI& handles, uint16_t total_len,
1696                                               uint8_t* value, void* data) {
1697     if (!instance) {
1698       return;
1699     }
1700 
1701     if (status != GATT_SUCCESS) {
1702       bluetooth::log::error("conn_id={:#} multi read failed {:#x}", conn_id, status);
1703       instance->OnCharacteristicValueChanged(conn_id, status, 0, 0, nullptr, nullptr, false);
1704       return;
1705     }
1706 
1707     size_t position = 0;
1708     int index = 0;
1709     while (position != total_len) {
1710       uint8_t* ptr = value + position;
1711       uint16_t len;
1712       STREAM_TO_UINT16(len, ptr);
1713       uint16_t hdl = handles.handles[index];
1714 
1715       if (position + len >= total_len) {
1716         bluetooth::log::warn(
1717                 "Multi read was too long, value truncated conn_id: {:#x} handle: {:#x}, position: "
1718                 "{:#x}, len: {:#x}, total_len: {:#x}, data: {}",
1719                 conn_id, hdl, position, len, total_len, base::HexEncode(value, total_len));
1720         break;
1721       }
1722 
1723       instance->OnCharacteristicValueChanged(conn_id, status, hdl, len, ptr,
1724                                              ((index == (handles.num_attr - 1)) ? data : nullptr),
1725                                              false);
1726       position += len + 2; /* skip the length of data */
1727       index++;
1728     }
1729 
1730     if (handles.num_attr != index) {
1731       bluetooth::log::warn("Attempted to read {} handles, but received just {} values",
1732                            +handles.num_attr, index);
1733     }
1734   }
1735 };
1736 }  // namespace
1737 
Initialize(bluetooth::vc::VolumeControlCallbacks * callbacks,const base::Closure & initCb)1738 void VolumeControl::Initialize(bluetooth::vc::VolumeControlCallbacks* callbacks,
1739                                const base::Closure& initCb) {
1740   std::scoped_lock<std::mutex> lock(instance_mutex);
1741   if (instance) {
1742     bluetooth::log::error("Already initialized!");
1743     return;
1744   }
1745 
1746   instance = new VolumeControlImpl(callbacks, initCb);
1747 }
1748 
IsVolumeControlRunning()1749 bool VolumeControl::IsVolumeControlRunning() { return instance; }
1750 
Get(void)1751 VolumeControl* VolumeControl::Get(void) {
1752   bluetooth::log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
1753   return instance;
1754 }
1755 
AddFromStorage(const RawAddress & address)1756 void VolumeControl::AddFromStorage(const RawAddress& address) {
1757   if (!instance) {
1758     bluetooth::log::error("Not initialized yet");
1759     return;
1760   }
1761 
1762   instance->AddFromStorage(address);
1763 }
1764 
CleanUp()1765 void VolumeControl::CleanUp() {
1766   std::scoped_lock<std::mutex> lock(instance_mutex);
1767   if (!instance) {
1768     bluetooth::log::error("Not initialized!");
1769     return;
1770   }
1771 
1772   VolumeControlImpl* ptr = instance;
1773   instance = nullptr;
1774 
1775   ptr->CleanUp();
1776 
1777   delete ptr;
1778 }
1779 
DebugDump(int fd)1780 void VolumeControl::DebugDump(int fd) {
1781   std::scoped_lock<std::mutex> lock(instance_mutex);
1782   dprintf(fd, "Volume Control Manager:\n");
1783   if (instance) {
1784     instance->Dump(fd);
1785   }
1786   dprintf(fd, "\n");
1787 }
1788