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