• Home
  • 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 "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