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