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