• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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