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