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