1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "gd/metrics/chromeos/metrics_event.h"
17
18 #include <base/files/file_path.h>
19 #include <base/files/file_util.h>
20 #include <base/strings/pattern.h>
21 #include <base/strings/string_number_conversions.h>
22 #include <base/strings/string_util.h>
23 #include <base/strings/stringprintf.h>
24
25 #include <map>
26 #include <utility>
27
28 #include "gd/common/init_flags.h"
29 #include "hci/hci_packets.h"
30 #include "include/hardware/bluetooth.h"
31 #include "include/hardware/bt_av.h"
32 #include "include/hardware/bt_hf.h"
33 #include "include/hardware/bt_hh.h"
34 #include "stack/include/hci_error_code.h"
35
36 namespace bluetooth {
37 namespace metrics {
38
39 namespace {
40 // these consts path below are for getting the chipset info
41 constexpr char kChipsetInfoWlanDirPath[] = "/sys/class/net/wlan0/device";
42 constexpr char kChipsetInfoMlanDirPath[] = "/sys/class/net/mlan0/device";
43 constexpr char kChipsetInfoModaliasPath[] = "/sys/class/bluetooth/hci%d/device/modalias";
44 constexpr char kChipInfoModuleDirPath[] = "/sys/class/bluetooth/hci%d/device/driver/module";
45 } // namespace
46
47 // topshim::btif::BtBondState is a copy of hardware/bluetooth.h:bt_bond_state_t
48 typedef bt_bond_state_t BtBondState;
49 // topshim::btif::BtAclState is a copy of hardware/bluetooth.h:bt_acl_state_t
50 typedef bt_acl_state_t BtAclState;
51 // topshim::btif::BtConnectionDirection is a copy of hardware/bluetooth.h:bt_conn_direction_t
52 typedef bt_conn_direction_t BtConnectionDirection;
53 // topshim::btif::BtStatus is a copy of hardware/bluetooth.h:bt_status_t
54 typedef bt_status_t BtStatus;
55 // topshim::profile::a2dp::BtavConnectionState is a copy of hardware/bt_av.h:btav_connection_state_t
56 typedef btav_connection_state_t BtavConnectionState;
57 // topshim::profile::hid_host::BthhConnectionState is a copy of hardware/bt_hh.h:bthh_connection_state_t
58 typedef bthh_connection_state_t BthhConnectionState;
59 // topshim::profile::hid_host::BthfConnectionState is a copy of hardware/bt_hh.h:bthf_connection_state_t
60 typedef headset::bthf_connection_state_t BthfConnectionState;
61
62 // A copy of topshim::btif::BtDeviceType
63 enum class BtDeviceType {
64 Unknown = 0,
65 Bredr,
66 Ble,
67 Dual,
68 };
69
70 // A normalized connection state ENUM definition all profiles
71 enum class ProfilesConnectionState {
72 DISCONNECTED = 0,
73 CONNECTING,
74 CONNECTED,
75 DISCONNECTING,
76 UNKNOWN,
77 };
78
79 // ENUM definition for Bluetooth profiles in sync with ::uuid::Profiles
80 enum class ProfilesFloss {
81 A2dpSink = 0,
82 A2dpSource,
83 AdvAudioDist,
84 Hsp,
85 HspAg,
86 Hfp,
87 HfpAg,
88 AvrcpController,
89 AvrcpTarget,
90 ObexObjectPush,
91 Hid,
92 Hogp,
93 Panu,
94 Nap,
95 Bnep,
96 PbapPce,
97 PbapPse,
98 Map,
99 Mns,
100 Mas,
101 Sap,
102 HearingAid,
103 LeAudio,
104 Dip,
105 VolumeControl,
106 GenericMediaControl,
107 MediaControl,
108 CoordinatedSet,
109 };
110
StatusToPairingState(uint32_t status)111 static PairingState StatusToPairingState(uint32_t status) {
112 switch ((BtStatus)status) {
113 case BtStatus::BT_STATUS_SUCCESS:
114 return PairingState::PAIR_SUCCEED;
115 case BtStatus::BT_STATUS_FAIL:
116 return PairingState::PAIR_FAIL_FAILED;
117 case BtStatus::BT_STATUS_NOMEM:
118 return PairingState::PAIR_FAIL_NO_RESOURCES;
119 case BtStatus::BT_STATUS_BUSY:
120 return PairingState::PAIR_FAIL_BUSY;
121 case BtStatus::BT_STATUS_UNSUPPORTED:
122 return PairingState::PAIR_FAIL_NOT_SUPPORTED;
123 case BtStatus::BT_STATUS_PARM_INVALID:
124 return PairingState::PAIR_FAIL_INVALID_PARAMS;
125 case BtStatus::BT_STATUS_AUTH_FAILURE:
126 return PairingState::PAIR_FAIL_AUTH_FAILED;
127 case BtStatus::BT_STATUS_RMT_DEV_DOWN:
128 return PairingState::PAIR_FAIL_ESTABLISH_CONN;
129 case BtStatus::BT_STATUS_AUTH_REJECTED:
130 return PairingState::PAIR_FAIL_AUTH_FAILED;
131 case BtStatus::BT_STATUS_NOT_READY:
132 case BtStatus::BT_STATUS_DONE:
133 case BtStatus::BT_STATUS_UNHANDLED:
134 default:
135 return PairingState::PAIR_FAIL_UNKNOWN;
136 }
137 }
138
FailReasonToPairingState(int32_t fail_reason)139 static PairingState FailReasonToPairingState(int32_t fail_reason) {
140 switch ((hci::ErrorCode)fail_reason) {
141 case hci::ErrorCode::SUCCESS:
142 return PairingState::PAIR_SUCCEED;
143 case hci::ErrorCode::UNKNOWN_HCI_COMMAND:
144 return PairingState::PAIR_FAIL_UNKNOWN_COMMAND;
145 case hci::ErrorCode::UNKNOWN_CONNECTION:
146 return PairingState::PAIR_FAIL_INVALID_PARAMS;
147 case hci::ErrorCode::HARDWARE_FAILURE:
148 return PairingState::PAIR_FAIL_FAILED;
149 case hci::ErrorCode::PAGE_TIMEOUT:
150 return PairingState::PAIR_FAIL_ESTABLISH_CONN;
151 case hci::ErrorCode::AUTHENTICATION_FAILURE:
152 return PairingState::PAIR_FAIL_AUTH_FAILED;
153 case hci::ErrorCode::PIN_OR_KEY_MISSING:
154 return PairingState::PAIR_FAIL_AUTH_FAILED;
155 case hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED:
156 return PairingState::PAIR_FAIL_NO_RESOURCES;
157 case hci::ErrorCode::CONNECTION_TIMEOUT:
158 return PairingState::PAIR_FAIL_ESTABLISH_CONN;
159 case hci::ErrorCode::CONNECTION_LIMIT_EXCEEDED:
160 return PairingState::PAIR_FAIL_NO_RESOURCES;
161 case hci::ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED:
162 return PairingState::PAIR_FAIL_NO_RESOURCES;
163 case hci::ErrorCode::CONNECTION_ALREADY_EXISTS:
164 return PairingState::PAIR_FAIL_ALREADY_PAIRED;
165 case hci::ErrorCode::COMMAND_DISALLOWED:
166 return PairingState::PAIR_FAIL_FAILED;
167 case hci::ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES:
168 return PairingState::PAIR_FAIL_NO_RESOURCES;
169 case hci::ErrorCode::CONNECTION_REJECTED_SECURITY_REASONS:
170 return PairingState::PAIR_FAIL_AUTH_FAILED;
171 case hci::ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR:
172 return PairingState::PAIR_FAIL_INVALID_PARAMS;
173 case hci::ErrorCode::CONNECTION_ACCEPT_TIMEOUT:
174 return PairingState::PAIR_FAIL_ESTABLISH_CONN;
175 case hci::ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE:
176 return PairingState::PAIR_FAIL_NOT_SUPPORTED;
177 case hci::ErrorCode::INVALID_HCI_COMMAND_PARAMETERS:
178 return PairingState::PAIR_FAIL_INVALID_PARAMS;
179 case hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION:
180 return PairingState::PAIR_FAIL_DISCONNECTED;
181 case hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES:
182 return PairingState::PAIR_FAIL_DISCONNECTED;
183 case hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF:
184 return PairingState::PAIR_FAIL_DISCONNECTED;
185 case hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST:
186 return PairingState::PAIR_FAIL_DISCONNECTED;
187 case hci::ErrorCode::REPEATED_ATTEMPTS:
188 return PairingState::PAIR_FAIL_BUSY;
189 case hci::ErrorCode::PAIRING_NOT_ALLOWED:
190 return PairingState::PAIR_FAIL_FAILED;
191 case hci::ErrorCode::UNKNOWN_LMP_PDU:
192 return PairingState::PAIR_FAIL_FAILED;
193 case hci::ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE:
194 return PairingState::PAIR_FAIL_NOT_SUPPORTED;
195 case hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS:
196 return PairingState::PAIR_FAIL_INVALID_PARAMS;
197 case hci::ErrorCode::UNSPECIFIED_ERROR:
198 return PairingState::PAIR_FAIL_UNKNOWN;
199 case hci::ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER:
200 return PairingState::PAIR_FAIL_NOT_SUPPORTED;
201 case hci::ErrorCode::ROLE_CHANGE_NOT_ALLOWED:
202 return PairingState::PAIR_FAIL_FAILED;
203 case hci::ErrorCode::TRANSACTION_RESPONSE_TIMEOUT:
204 return PairingState::PAIR_FAIL_TIMEOUT;
205 case hci::ErrorCode::LINK_LAYER_COLLISION:
206 return PairingState::PAIR_FAIL_FAILED;
207 case hci::ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE:
208 return PairingState::PAIR_FAIL_AUTH_FAILED;
209 case hci::ErrorCode::ROLE_SWITCH_FAILED:
210 return PairingState::PAIR_FAIL_FAILED;
211 case hci::ErrorCode::HOST_BUSY:
212 return PairingState::PAIR_FAIL_BUSY;
213 case hci::ErrorCode::CONTROLLER_BUSY:
214 return PairingState::PAIR_FAIL_BUSY;
215 case hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT:
216 return PairingState::PAIR_FAIL_ESTABLISH_CONN;
217 case hci::ErrorCode::LIMIT_REACHED:
218 return PairingState::PAIR_FAIL_NO_RESOURCES;
219 case hci::ErrorCode::PACKET_TOO_LONG:
220 return PairingState::PAIR_FAIL_INVALID_PARAMS;
221 case hci::ErrorCode::SCO_OFFSET_REJECTED:
222 case hci::ErrorCode::SCO_INTERVAL_REJECTED:
223 case hci::ErrorCode::SCO_AIR_MODE_REJECTED:
224 case hci::ErrorCode::ADVERTISING_TIMEOUT:
225 case hci::ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER:
226 case hci::ErrorCode::STATUS_UNKNOWN:
227 return PairingState::PAIR_FAIL_UNKNOWN;
228 default:
229 return PairingState::PAIR_FAIL_UNKNOWN;
230 }
231 }
232
ToAdapterState(uint32_t state)233 AdapterState ToAdapterState(uint32_t state) {
234 return state == 1 ? AdapterState::ON : AdapterState::OFF;
235 }
236
ToPairingDeviceType(std::string addr,uint32_t device_type)237 ConnectionType ToPairingDeviceType(std::string addr, uint32_t device_type) {
238 // A map stores the pending ConnectionType used to match a pairing event with unknown type.
239 // map<address, type>
240 static std::map<std::string, ConnectionType> pending_type;
241
242 switch ((BtDeviceType)device_type) {
243 case BtDeviceType::Ble:
244 pending_type[addr] = ConnectionType::CONN_TYPE_LE;
245 return ConnectionType::CONN_TYPE_LE;
246 case BtDeviceType::Bredr:
247 pending_type[addr] = ConnectionType::CONN_TYPE_BREDR;
248 return ConnectionType::CONN_TYPE_BREDR;
249 case BtDeviceType::Dual:
250 case BtDeviceType::Unknown:
251 if (pending_type.find(addr) != pending_type.end()) {
252 return pending_type[addr];
253 } else {
254 return ConnectionType::CONN_TYPE_UNKNOWN;
255 }
256 }
257 }
258
ToPairingState(uint32_t status,uint32_t bond_state,int32_t fail_reason)259 PairingState ToPairingState(uint32_t status, uint32_t bond_state, int32_t fail_reason) {
260 PairingState pairing_state = PairingState::PAIR_FAIL_UNKNOWN;
261
262 // The Bonding is a transitional state during the pairing process. Ignore it by returning the starting again.
263 if ((BtBondState)bond_state == BtBondState::BT_BOND_STATE_BONDING) return PairingState::PAIR_STARTING;
264
265 if ((BtStatus)status == BtStatus::BT_STATUS_SUCCESS && (hci::ErrorCode)fail_reason == hci::ErrorCode::SUCCESS) {
266 if ((BtBondState)bond_state == BtBondState::BT_BOND_STATE_BONDED) {
267 return PairingState::PAIR_SUCCEED;
268 } else {
269 return PairingState::PAIR_FAIL_CANCELLED;
270 }
271 }
272
273 // When both status and fail reason are provided and disagree with each other, overwrite status with the fail reason
274 // as fail reason is generated closer to the HCI and provides a more accurate description.
275 if (status) pairing_state = StatusToPairingState(status);
276 if (fail_reason) pairing_state = FailReasonToPairingState(fail_reason);
277
278 return pairing_state;
279 }
280
StatusToProfileConnectionState(uint32_t status,StateChangeType type)281 int64_t StatusToProfileConnectionState(uint32_t status, StateChangeType type) {
282 int64_t state;
283 if (StateChangeType::STATE_CHANGE_TYPE_CONNECT == type) {
284 switch ((BtStatus)status) {
285 case BtStatus::BT_STATUS_SUCCESS:
286 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_SUCCEED;
287 break;
288 case BtStatus::BT_STATUS_BUSY:
289 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_BUSY_CONNECTING;
290 break;
291 case BtStatus::BT_STATUS_DONE:
292 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_ALREADY_CONNECTED;
293 break;
294 case BtStatus::BT_STATUS_UNSUPPORTED:
295 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_PROFILE_NOT_SUPPORTED;
296 break;
297 case BtStatus::BT_STATUS_PARM_INVALID:
298 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_UNKNOWN_ERROR;
299 break;
300 case BtStatus::BT_STATUS_AUTH_FAILURE:
301 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_CONNECTION_REFUSED;
302 break;
303 case BtStatus::BT_STATUS_RMT_DEV_DOWN:
304 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_REMOTE_UNAVAILABLE;
305 break;
306 case BtStatus::BT_STATUS_AUTH_REJECTED:
307 case BtStatus::BT_STATUS_FAIL:
308 case BtStatus::BT_STATUS_NOT_READY:
309 case BtStatus::BT_STATUS_NOMEM:
310 case BtStatus::BT_STATUS_UNHANDLED:
311 default:
312 state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_UNKNOWN_ERROR;
313 break;
314 }
315 } else {
316 switch ((BtStatus)status) {
317 case BtStatus::BT_STATUS_SUCCESS:
318 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_SUCCEED;
319 break;
320 case BtStatus::BT_STATUS_BUSY:
321 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_BUSY_DISCONNECTING;
322 break;
323 case BtStatus::BT_STATUS_DONE:
324 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_ALREADY_DISCONNECTED;
325 break;
326 case BtStatus::BT_STATUS_UNSUPPORTED:
327 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_UNKNOWN_ERROR;
328 break;
329 case BtStatus::BT_STATUS_PARM_INVALID:
330 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_INVALID_PARAMS;
331 break;
332 case BtStatus::BT_STATUS_AUTH_FAILURE:
333 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_DISCONNECTION_REFUSED;
334 break;
335 case BtStatus::BT_STATUS_RMT_DEV_DOWN:
336 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_UNKNOWN_ERROR;
337 break;
338 case BtStatus::BT_STATUS_AUTH_REJECTED:
339 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_DISCONNECTION_REFUSED;
340 break;
341 case BtStatus::BT_STATUS_FAIL:
342 case BtStatus::BT_STATUS_NOT_READY:
343 case BtStatus::BT_STATUS_NOMEM:
344 case BtStatus::BT_STATUS_UNHANDLED:
345 default:
346 state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_UNKNOWN_ERROR;
347 break;
348 }
349 }
350
351 return state;
352 }
353
ToProfileConnectionState(uint32_t profile,uint32_t state)354 static std::pair<uint32_t, uint32_t> ToProfileConnectionState(uint32_t profile, uint32_t state) {
355 std::pair<uint32_t, uint32_t> output;
356
357 switch ((ProfilesFloss)profile) {
358 case ProfilesFloss::A2dpSink:
359 output.first = (uint32_t)Profile::A2DP;
360 switch ((BtavConnectionState)state) {
361 case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTED:
362 output.second = (uint32_t)ProfilesConnectionState::CONNECTED;
363 break;
364 case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTING:
365 output.second = (uint32_t)ProfilesConnectionState::CONNECTING;
366 break;
367 case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTED:
368 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTED;
369 break;
370 case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTING:
371 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTING;
372 break;
373 default:
374 output.second = (uint32_t)ProfilesConnectionState::UNKNOWN;
375 break;
376 }
377 break;
378 // case ProfilesFloss::A2dpSource:
379 // case ProfilesFloss::AdvAudioDist:
380 // case ProfilesFloss::Hsp:
381 // case ProfilesFloss::HspAg:
382 case ProfilesFloss::Hfp:
383 output.first = (uint32_t)Profile::HFP;
384 switch ((BthfConnectionState)state) {
385 case BthfConnectionState::BTHF_CONNECTION_STATE_DISCONNECTED:
386 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTED;
387 break;
388 case BthfConnectionState::BTHF_CONNECTION_STATE_CONNECTING:
389 output.second = (uint32_t)ProfilesConnectionState::CONNECTING;
390 break;
391 case BthfConnectionState::BTHF_CONNECTION_STATE_CONNECTED:
392 case BthfConnectionState::BTHF_CONNECTION_STATE_SLC_CONNECTED:
393 output.second = (uint32_t)ProfilesConnectionState::CONNECTED;
394 break;
395 case BthfConnectionState::BTHF_CONNECTION_STATE_DISCONNECTING:
396 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTING;
397 break;
398 default:
399 output.second = (uint32_t)ProfilesConnectionState::UNKNOWN;
400 break;
401 }
402 break;
403 // case ProfilesFloss::HfpAg:
404 case ProfilesFloss::AvrcpController:
405 output.first = (uint32_t)Profile::AVRCP;
406 switch ((BtavConnectionState)state) {
407 case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTED:
408 output.second = (uint32_t)ProfilesConnectionState::CONNECTED;
409 break;
410 case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTING:
411 output.second = (uint32_t)ProfilesConnectionState::CONNECTING;
412 break;
413 case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTED:
414 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTED;
415 break;
416 case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTING:
417 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTING;
418 break;
419 default:
420 output.second = (uint32_t)ProfilesConnectionState::UNKNOWN;
421 break;
422 }
423 break;
424 // case ProfilesFloss::AvrcpTarget:
425 // case ProfilesFloss::ObexObjectPush:
426 case ProfilesFloss::Hid:
427 case ProfilesFloss::Hogp:
428 output.first = (uint32_t)Profile::HID;
429 switch ((BthhConnectionState)state) {
430 case BthhConnectionState::BTHH_CONN_STATE_CONNECTED:
431 output.second = (uint32_t)ProfilesConnectionState::CONNECTED;
432 break;
433 case BthhConnectionState::BTHH_CONN_STATE_CONNECTING:
434 output.second = (uint32_t)ProfilesConnectionState::CONNECTING;
435 break;
436 case BthhConnectionState::BTHH_CONN_STATE_DISCONNECTED:
437 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTED;
438 break;
439 case BthhConnectionState::BTHH_CONN_STATE_DISCONNECTING:
440 output.second = (uint32_t)ProfilesConnectionState::DISCONNECTING;
441 break;
442 case BthhConnectionState::BTHH_CONN_STATE_UNKNOWN:
443 output.second = (uint32_t)ProfilesConnectionState::UNKNOWN;
444 break;
445 }
446 break;
447 // case ProfilesFloss::Panu:
448 // case ProfilesFloss::Nap:
449 // case ProfilesFloss::Bnep:
450 // case ProfilesFloss::PbapPce:
451 // case ProfilesFloss::PbapPse:
452 // case ProfilesFloss::Map:
453 // case ProfilesFloss::Mns:
454 // case ProfilesFloss::Mas:
455 // case ProfilesFloss::Sap:
456 // case ProfilesFloss::HearingAid:
457 // case ProfilesFloss::LeAudio:
458 // case ProfilesFloss::Dip:
459 // case ProfilesFloss::VolumeControl:
460 // case ProfilesFloss::GenericMediaControl:
461 // case ProfilesFloss::MediaControl:
462 // case ProfilesFloss::CoordinatedSet:
463 default:
464 output = std::make_pair((uint32_t)Profile::UNKNOWN, state);
465 break;
466 }
467
468 return output;
469 }
470
ToProfileConnectionEvent(std::string addr,uint32_t profile,uint32_t status,uint32_t state)471 ProfileConnectionEvent ToProfileConnectionEvent(std::string addr, uint32_t profile, uint32_t status, uint32_t state) {
472 ProfileConnectionEvent event;
473 // A map stores the pending StateChangeType used to match a (dis)connection event with unknown type.
474 // map<std::pair<address, profile>, type>
475 static std::map<std::pair<std::string, uint32_t>, StateChangeType> pending_type;
476
477 auto profile_state_pair = ToProfileConnectionState(profile, state);
478 auto key = std::make_pair(addr, profile_state_pair.first);
479 event.profile = (int64_t)profile_state_pair.first;
480
481 switch ((ProfilesConnectionState)profile_state_pair.second) {
482 case ProfilesConnectionState::CONNECTED:
483 event.type = (int64_t)StateChangeType::STATE_CHANGE_TYPE_CONNECT;
484 event.state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_SUCCEED;
485 pending_type.erase(key);
486 break;
487 case ProfilesConnectionState::CONNECTING:
488 event.type = (int64_t)StateChangeType::STATE_CHANGE_TYPE_CONNECT;
489 event.state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_STARTING;
490 pending_type[key] = StateChangeType::STATE_CHANGE_TYPE_CONNECT;
491 break;
492 case ProfilesConnectionState::DISCONNECTED:
493 event.type = pending_type.find(key) != pending_type.end()
494 ? (int64_t)pending_type[key]
495 : (int64_t)StateChangeType::STATE_CHANGE_TYPE_DISCONNECT;
496 // If the profile successfully disconnected for a connect intent, i.e., a connection is attempted but received a
497 // disconnection state update. Report this as an unknown error.
498 if (StateChangeType::STATE_CHANGE_TYPE_CONNECT == (StateChangeType)event.type &&
499 BtStatus::BT_STATUS_SUCCESS == (BtStatus)status) {
500 event.state = (int64_t)MetricProfileConnectionStatus::PROFILE_CONN_STATE_UNKNOWN_ERROR;
501 } else {
502 event.state = StatusToProfileConnectionState(status, (StateChangeType)event.type);
503 }
504 pending_type.erase(key);
505 break;
506 case ProfilesConnectionState::DISCONNECTING:
507 event.type = (int64_t)StateChangeType::STATE_CHANGE_TYPE_DISCONNECT;
508 event.state = (int64_t)MetricProfileDisconnectionStatus::PROFILE_DISCONN_STATE_STARTING;
509 pending_type[key] = StateChangeType::STATE_CHANGE_TYPE_DISCONNECT;
510 break;
511 default:
512 event.profile = (int64_t)Profile::UNKNOWN;
513 break;
514 }
515
516 return event;
517 }
518
ToAclConnectionStatus(uint32_t status,StateChangeType type,uint32_t hci_reason)519 static int64_t ToAclConnectionStatus(uint32_t status, StateChangeType type, uint32_t hci_reason) {
520 int64_t state;
521 if (StateChangeType::STATE_CHANGE_TYPE_CONNECT == type) {
522 switch ((BtStatus)status) {
523 case BtStatus::BT_STATUS_SUCCESS:
524 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_SUCCEED;
525 break;
526 case BtStatus::BT_STATUS_BUSY:
527 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_BUSY;
528 break;
529 case BtStatus::BT_STATUS_DONE:
530 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_ALREADY;
531 break;
532 case BtStatus::BT_STATUS_UNSUPPORTED:
533 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_NOT_SUPPORTED;
534 break;
535 case BtStatus::BT_STATUS_PARM_INVALID:
536 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_INVALID_PARAMS;
537 break;
538 case BtStatus::BT_STATUS_AUTH_FAILURE:
539 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_AUTH_FAILED;
540 break;
541 case BtStatus::BT_STATUS_RMT_DEV_DOWN:
542 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_DISCONNECTED;
543 break;
544 case BtStatus::BT_STATUS_AUTH_REJECTED:
545 case BtStatus::BT_STATUS_FAIL:
546 case BtStatus::BT_STATUS_NOT_READY:
547 case BtStatus::BT_STATUS_NOMEM:
548 case BtStatus::BT_STATUS_UNHANDLED:
549 default:
550 state = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_UNKNOWN;
551 break;
552 }
553 } else {
554 switch (hci_reason) {
555 case HCI_ERR_CONNECTION_TOUT:
556 state = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_TIMEOUT;
557 break;
558 case HCI_ERR_PEER_USER:
559 case HCI_ERR_REMOTE_LOW_RESOURCE:
560 case HCI_ERR_REMOTE_POWER_OFF:
561 state = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_REMOTE;
562 break;
563 case HCI_ERR_CONN_CAUSE_LOCAL_HOST:
564 state = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_LOCAL_HOST;
565 // TODO: distinguish from ACL_DISCONN_STATE_LOCAL_HOST_SUSPEND
566 break;
567 case HCI_ERR_AUTH_FAILURE:
568 case HCI_ERR_KEY_MISSING:
569 case HCI_ERR_HOST_REJECT_SECURITY:
570 state = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_AUTH_FAILURE;
571 break;
572 default:
573 state = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_UNKNOWN;
574 break;
575 }
576 }
577
578 return state;
579 }
580
581 // pending acl conn event is map<addr, pair<state, time>>
582 static std::map<std::string, std::pair<uint32_t, int64_t>> pending_acl_events;
583
PendingAclConnectAttemptEvent(std::string addr,int64_t time,uint32_t acl_state)584 void PendingAclConnectAttemptEvent(std::string addr, int64_t time, uint32_t acl_state) {
585 pending_acl_events[addr] = std::make_pair(acl_state, time);
586 }
587
ToAclConnectionEvent(std::string addr,int64_t time,uint32_t acl_status,uint32_t acl_state,uint32_t direction,uint32_t hci_reason)588 AclConnectionEvent ToAclConnectionEvent(
589 std::string addr, int64_t time, uint32_t acl_status, uint32_t acl_state, uint32_t direction, uint32_t hci_reason) {
590 AclConnectionEvent event;
591
592 if (pending_acl_events.find(addr) == pending_acl_events.end()) {
593 // No attempt found! Assume initiated by system.
594 event.initiator = (int64_t)MetricAclConnectionInitiator::ACL_CONNECTION_INITIATOR_SYSTEM;
595 event.direction = direction;
596 event.start_time = time;
597
598 // There is no failed disconnection. Therefore on failure, assume it's a connection attempt.
599 if (acl_state == (uint32_t)BtAclState::BT_ACL_STATE_CONNECTED ||
600 acl_status != (uint32_t)BtStatus::BT_STATUS_SUCCESS) {
601 event.state = (int64_t)StateChangeType::STATE_CHANGE_TYPE_CONNECT;
602 } else {
603 event.state = (int64_t)StateChangeType::STATE_CHANGE_TYPE_DISCONNECT;
604 }
605 } else {
606 // connection attempt found. Assume initiated by client.
607 std::pair<uint32_t, int64_t> pending_event = pending_acl_events[addr];
608 pending_acl_events.erase(addr);
609 event.initiator = (int64_t)MetricAclConnectionInitiator::ACL_CONNECTION_INITIATOR_CLIENT;
610 event.direction = (int64_t)MetricAclConnectionDirection::ACL_CONNECTION_OUTGOING;
611 event.start_time = pending_event.second;
612
613 if (pending_event.first == (uint32_t)BtAclState::BT_ACL_STATE_CONNECTED) {
614 event.state = (int64_t)StateChangeType::STATE_CHANGE_TYPE_CONNECT;
615 } else {
616 event.state = (int64_t)StateChangeType::STATE_CHANGE_TYPE_DISCONNECT;
617 }
618 }
619
620 if (event.state == (int64_t)StateChangeType::STATE_CHANGE_TYPE_CONNECT) {
621 event.start_status = (int64_t)MetricAclConnectionStatus::ACL_CONN_STATE_STARTING;
622 } else {
623 event.start_status = (int64_t)MetricAclDisconnectionStatus::ACL_DISCONN_STATE_STARTING;
624 }
625
626 event.status = ToAclConnectionStatus(acl_status, (StateChangeType)event.state, hci_reason);
627
628 return event;
629 }
630
GetChipsetInfoId(const char * path,const char * file)631 static int64_t GetChipsetInfoId(const char* path, const char* file) {
632 std::string content;
633 int64_t id;
634
635 if (base::ReadFileToString(base::FilePath(path).Append(file), &content)) {
636 if (base::HexStringToInt64(base::CollapseWhitespaceASCII(content, false), &id)) {
637 return id;
638 }
639 }
640 return 0;
641 }
642
GetChipsetInfoModuleName()643 static std::string GetChipsetInfoModuleName() {
644 std::string module;
645 int adapter_index = bluetooth::common::InitFlags::GetAdapterIndex();
646 std::string path = base::StringPrintf(kChipsetInfoModaliasPath, adapter_index);
647
648 if (base::ReadFileToString(base::FilePath(path), &module)) {
649 return base::CollapseWhitespaceASCII(module, false);
650 }
651 return "";
652 }
653
GetChipsetInfoTransport(void)654 static MetricTransportType GetChipsetInfoTransport(void) {
655 MetricTransportType transport = MetricTransportType::TRANSPORT_TYPE_UNKNOWN;
656 base::FilePath module_realpath;
657 std::string module_name;
658 int adapter_index = bluetooth::common::InitFlags::GetAdapterIndex();
659 std::string path = base::StringPrintf(kChipInfoModuleDirPath, adapter_index);
660
661 // examples of module_realpath: /sys/module/btusb and /sys/module/hci_uart
662 module_realpath = base::MakeAbsoluteFilePath(base::FilePath(path));
663 if (module_realpath.empty()) {
664 return transport;
665 }
666
667 module_name = module_realpath.BaseName().value();
668 if (base::MatchPattern(module_name, "*usb*"))
669 transport = MetricTransportType::TRANSPORT_TYPE_USB;
670 else if (base::MatchPattern(module_name, "*uart*"))
671 transport = MetricTransportType::TRANSPORT_TYPE_UART;
672 else if (base::MatchPattern(module_name, "*sdio*"))
673 transport = MetricTransportType::TRANSPORT_TYPE_SDIO;
674
675 return transport;
676 }
677
GetMetricsChipsetInfo()678 MetricsChipsetInfo GetMetricsChipsetInfo() {
679 MetricsChipsetInfo info;
680
681 info.vid = GetChipsetInfoId(kChipsetInfoWlanDirPath, "vendor");
682 info.pid = GetChipsetInfoId(kChipsetInfoWlanDirPath, "device");
683
684 if (!info.vid || !info.pid) {
685 info.vid = GetChipsetInfoId(kChipsetInfoMlanDirPath, "vendor");
686 info.pid = GetChipsetInfoId(kChipsetInfoMlanDirPath, "device");
687 }
688
689 if (!info.vid || !info.pid) {
690 info.chipset_string = GetChipsetInfoModuleName();
691 }
692
693 info.transport = (int)GetChipsetInfoTransport();
694 return info;
695 }
696
697 } // namespace metrics
698 } // namespace bluetooth