1 /*
2  * Copyright 2024 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 "bluetooth_event.h"
17 
18 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
19 
20 #include "main/shim/helpers.h"
21 #include "os/metrics.h"
22 
23 // TODO(b/369381361) Enfore -Wmissing-prototypes
24 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
25 
26 namespace bluetooth {
27 namespace metrics {
28 
29 using android::bluetooth::EventType;
30 using android::bluetooth::State;
31 using hci::ErrorCode;
32 
MapErrorCodeToState(ErrorCode reason)33 State MapErrorCodeToState(ErrorCode reason) {
34   // TODO - map the error codes to the state enum variants.
35   switch (reason) {
36     case ErrorCode::SUCCESS:
37       return State::SUCCESS;
38     // Timeout related errors
39     case ErrorCode::PAGE_TIMEOUT:
40       return State::PAGE_TIMEOUT;
41     case ErrorCode::CONNECTION_TIMEOUT:
42       return State::CONNECTION_TIMEOUT;
43     case ErrorCode::CONNECTION_ACCEPT_TIMEOUT:
44       return State::CONNECTION_ACCEPT_TIMEOUT;
45     case ErrorCode::TRANSACTION_RESPONSE_TIMEOUT:
46       return State::TRANSACTION_RESPONSE_TIMEOUT;
47     case ErrorCode::AUTHENTICATION_FAILURE:
48       return State::AUTH_FAILURE;
49     case ErrorCode::REMOTE_USER_TERMINATED_CONNECTION:
50     case ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES:
51     case ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF:
52       return State::REMOTE_USER_TERMINATED_CONNECTION;
53     case ErrorCode::CONNECTION_ALREADY_EXISTS:
54       return State::ALREADY_CONNECTED;
55     case ErrorCode::REPEATED_ATTEMPTS:
56       return State::REPEATED_ATTEMPTS;
57     case ErrorCode::PIN_OR_KEY_MISSING:
58       return State::KEY_MISSING;
59     case ErrorCode::PAIRING_NOT_ALLOWED:
60       return State::PAIRING_NOT_ALLOWED;
61     case ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES:
62       return State::RESOURCES_EXCEEDED;
63     case ErrorCode::HARDWARE_FAILURE:
64       return State::HARDWARE_FAILURE;
65     case ErrorCode::MEMORY_CAPACITY_EXCEEDED:
66       return State::MEMORY_CAPACITY_EXCEEDED;
67     case ErrorCode::CONNECTION_LIMIT_EXCEEDED:
68       return State::CONNECTION_LIMIT_EXCEEDED;
69     case ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED:
70       return State::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED;
71     case ErrorCode::CONNECTION_REJECTED_SECURITY_REASONS:
72       return State::CONNECTION_REJECTED_SECURITY_REASONS;
73     case ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR:
74       return State::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR;
75     case ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE:
76       return State::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
77     case ErrorCode::INVALID_HCI_COMMAND_PARAMETERS:
78       return State::INVALID_HCI_COMMAND_PARAMETERS;
79     case ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST:
80       return State::CONNECTION_TERMINATED_BY_LOCAL_HOST;
81     case ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE:
82       return State::UNSUPPORTED_REMOTE_OR_LMP_FEATURE;
83     case ErrorCode::SCO_OFFSET_REJECTED:
84       return State::SCO_OFFSET_REJECTED;
85     case ErrorCode::SCO_INTERVAL_REJECTED:
86       return State::SCO_INTERVAL_REJECTED;
87     case ErrorCode::SCO_AIR_MODE_REJECTED:
88       return State::SCO_AIR_MODE_REJECTED;
89     case ErrorCode::INVALID_LMP_OR_LL_PARAMETERS:
90       return State::INVALID_LMP_OR_LL_PARAMETERS;
91     case ErrorCode::UNSPECIFIED_ERROR:
92       return State::UNSPECIFIED_ERROR;
93     case ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER:
94       return State::UNSUPPORTED_LMP_OR_LL_PARAMETER;
95     case ErrorCode::ROLE_CHANGE_NOT_ALLOWED:
96       return State::ROLE_CHANGE_NOT_ALLOWED;
97     case ErrorCode::LINK_LAYER_COLLISION:
98       return State::LINK_LAYER_COLLISION;
99     case ErrorCode::LMP_PDU_NOT_ALLOWED:
100       return State::LMP_PDU_NOT_ALLOWED;
101     case ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE:
102       return State::ENCRYPTION_MODE_NOT_ACCEPTABLE;
103     case ErrorCode::LINK_KEY_CANNOT_BE_CHANGED:
104       return State::LINK_KEY_CANNOT_BE_CHANGED;
105     case ErrorCode::REQUESTED_QOS_NOT_SUPPORTED:
106       return State::REQUESTED_QOS_NOT_SUPPORTED;
107     case ErrorCode::INSTANT_PASSED:
108       return State::INSTANT_PASSED;
109     case ErrorCode::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED:
110       return State::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED;
111     case ErrorCode::DIFFERENT_TRANSACTION_COLLISION:
112       return State::DIFFERENT_TRANSACTION_COLLISION;
113     case ErrorCode::QOS_UNACCEPTABLE_PARAMETERS:
114       return State::QOS_UNACCEPTABLE_PARAMETERS;
115     case ErrorCode::QOS_REJECTED:
116       return State::QOS_REJECTED;
117     case ErrorCode::CHANNEL_ASSESSMENT_NOT_SUPPORTED:
118       return State::CHANNEL_ASSESSMENT_NOT_SUPPORTED;
119     case ErrorCode::INSUFFICIENT_SECURITY:
120       return State::INSUFFICIENT_SECURITY;
121     case ErrorCode::PARAMETER_OUT_OF_MANDATORY_RANGE:
122       return State::PARAMETER_OUT_OF_MANDATORY_RANGE;
123     case ErrorCode::ROLE_SWITCH_PENDING:
124       return State::ROLE_SWITCH_PENDING;
125     case ErrorCode::RESERVED_SLOT_VIOLATION:
126       return State::RESERVED_SLOT_VIOLATION;
127     case ErrorCode::ROLE_SWITCH_FAILED:
128       return State::ROLE_SWITCH_FAILED;
129     case ErrorCode::EXTENDED_INQUIRY_RESPONSE_TOO_LARGE:
130       return State::EXTENDED_INQUIRY_RESPONSE_TOO_LARGE;
131     case ErrorCode::SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST:
132       return State::SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST;
133     case ErrorCode::HOST_BUSY_PAIRING:
134       return State::HOST_BUSY_PAIRING;
135     case ErrorCode::CONNECTION_REJECTED_NO_SUITABLE_CHANNEL_FOUND:
136       return State::CONNECTION_REJECTED_NO_SUITABLE_CHANNEL_FOUND;
137     case ErrorCode::CONTROLLER_BUSY:
138       return State::CONTROLLER_BUSY;
139     case ErrorCode::UNACCEPTABLE_CONNECTION_PARAMETERS:
140       return State::UNACCEPTABLE_CONNECTION_PARAMETERS;
141     case ErrorCode::ADVERTISING_TIMEOUT:
142       return State::ADVERTISING_TIMEOUT;
143     case ErrorCode::CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE:
144       return State::CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE;
145     case ErrorCode::CONNECTION_FAILED_ESTABLISHMENT:
146       return State::CONNECTION_FAILED_ESTABLISHMENT;
147     case ErrorCode::COARSE_CLOCK_ADJUSTMENT_REJECTED:
148       return State::COARSE_CLOCK_ADJUSTMENT_REJECTED;
149     case ErrorCode::TYPE0_SUBMAP_NOT_DEFINED:
150       return State::TYPE0_SUBMAP_NOT_DEFINED;
151     case ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER:
152       return State::UNKNOWN_ADVERTISING_IDENTIFIER;
153     case ErrorCode::LIMIT_REACHED:
154       return State::LIMIT_REACHED;
155     case ErrorCode::OPERATION_CANCELLED_BY_HOST:
156       return State::OPERATION_CANCELLED_BY_HOST;
157     case ErrorCode::PACKET_TOO_LONG:
158       return State::PACKET_TOO_LONG;
159     default:
160       return State::STATE_UNKNOWN;
161   }
162 }
163 
MapHCIStatusToState(tHCI_STATUS status)164 State MapHCIStatusToState(tHCI_STATUS status) {
165   // TODO - map the error codes to the state enum variants.
166   switch (status) {
167     case tHCI_STATUS::HCI_SUCCESS:
168       return State::SUCCESS;
169     // Timeout related errors
170     case tHCI_STATUS::HCI_ERR_PAGE_TIMEOUT:
171       return State::PAGE_TIMEOUT;
172     case tHCI_STATUS::HCI_ERR_CONNECTION_TOUT:
173       return State::CONNECTION_TIMEOUT;
174     case tHCI_STATUS::HCI_ERR_HOST_TIMEOUT:
175       return State::CONNECTION_ACCEPT_TIMEOUT;
176     case tHCI_STATUS::HCI_ERR_LMP_RESPONSE_TIMEOUT:
177       return State::TRANSACTION_RESPONSE_TIMEOUT;
178     case tHCI_STATUS::HCI_ERR_AUTH_FAILURE:
179       return State::AUTH_FAILURE;
180     case tHCI_STATUS::HCI_ERR_CONNECTION_EXISTS:
181       return State::ALREADY_CONNECTED;
182     case tHCI_STATUS::HCI_ERR_REPEATED_ATTEMPTS:
183       return State::REPEATED_ATTEMPTS;
184     case tHCI_STATUS::HCI_ERR_KEY_MISSING:
185       return State::KEY_MISSING;
186     case tHCI_STATUS::HCI_ERR_PAIRING_NOT_ALLOWED:
187       return State::PAIRING_NOT_ALLOWED;
188     case tHCI_STATUS::HCI_ERR_HOST_REJECT_RESOURCES:
189       return State::RESOURCES_EXCEEDED;
190     default:
191       return State::STATE_UNKNOWN;
192   }
193 }
194 
MapSmpStatusCodeToState(tSMP_STATUS status)195 State MapSmpStatusCodeToState(tSMP_STATUS status) {
196   switch (status) {
197     case tSMP_STATUS::SMP_SUCCESS:
198       return State::SUCCESS;
199     case tSMP_STATUS::SMP_PASSKEY_ENTRY_FAIL:
200       return State::PASSKEY_ENTRY_FAIL;
201     case tSMP_STATUS::SMP_OOB_FAIL:
202       return State::OOB_FAIL;
203     case tSMP_STATUS::SMP_PAIR_AUTH_FAIL:
204       return State::AUTH_FAILURE;
205     case tSMP_STATUS::SMP_CONFIRM_VALUE_ERR:
206       return State::CONFIRM_VALUE_ERROR;
207     case tSMP_STATUS::SMP_PAIR_NOT_SUPPORT:
208       return State::PAIRING_NOT_ALLOWED;
209     case tSMP_STATUS::SMP_ENC_KEY_SIZE:
210       return State::ENC_KEY_SIZE;
211     case tSMP_STATUS::SMP_INVALID_CMD:
212       return State::INVALID_CMD;
213     case tSMP_STATUS::SMP_PAIR_FAIL_UNKNOWN:
214       return State::STATE_UNKNOWN;  // Assuming this maps to the default
215     case tSMP_STATUS::SMP_REPEATED_ATTEMPTS:
216       return State::REPEATED_ATTEMPTS;
217     case tSMP_STATUS::SMP_INVALID_PARAMETERS:
218       return State::INVALID_PARAMETERS;
219     case tSMP_STATUS::SMP_DHKEY_CHK_FAIL:
220       return State::DHKEY_CHK_FAIL;
221     case tSMP_STATUS::SMP_NUMERIC_COMPAR_FAIL:
222       return State::NUMERIC_COMPARISON_FAIL;
223     case tSMP_STATUS::SMP_BR_PARING_IN_PROGR:
224       return State::BR_PAIRING_IN_PROGRESS;
225     case tSMP_STATUS::SMP_XTRANS_DERIVE_NOT_ALLOW:
226       return State::CROSS_TRANSPORT_NOT_ALLOWED;
227     case tSMP_STATUS::SMP_PAIR_INTERNAL_ERR:
228       return State::INTERNAL_ERROR;
229     case tSMP_STATUS::SMP_UNKNOWN_IO_CAP:
230       return State::UNKNOWN_IO_CAP;
231     case tSMP_STATUS::SMP_BUSY:
232       return State::BUSY_PAIRING;
233     case tSMP_STATUS::SMP_ENC_FAIL:
234       return State::ENCRYPTION_FAIL;
235     case tSMP_STATUS::SMP_STARTED:
236       return State::STATE_UNKNOWN;  // Assuming this maps to the default
237     case tSMP_STATUS::SMP_RSP_TIMEOUT:
238       return State::RESPONSE_TIMEOUT;
239     case tSMP_STATUS::SMP_FAIL:
240       return State::FAIL;
241     case tSMP_STATUS::SMP_CONN_TOUT:
242       return State::CONNECTION_TIMEOUT;
243     case tSMP_STATUS::SMP_SIRK_DEVICE_INVALID:
244       return State::SIRK_DEVICE_INVALID;
245     case tSMP_STATUS::SMP_USER_CANCELLED:
246       return State::USER_CANCELLATION;
247     default:
248       return State::STATE_UNKNOWN;
249   }
250 }
251 
LogIncomingAclStartEvent(const hci::Address & address)252 void LogIncomingAclStartEvent(const hci::Address& address) {
253   bluetooth::os::LogMetricBluetoothEvent(address, EventType::ACL_CONNECTION_RESPONDER,
254                                          State::START);
255 }
256 
LogAclCompletionEvent(const hci::Address & address,ErrorCode reason,bool is_locally_initiated)257 void LogAclCompletionEvent(const hci::Address& address, ErrorCode reason,
258                            bool is_locally_initiated) {
259   bluetooth::os::LogMetricBluetoothEvent(address,
260                                          is_locally_initiated ? EventType::ACL_CONNECTION_INITIATOR
261                                                               : EventType::ACL_CONNECTION_RESPONDER,
262                                          MapErrorCodeToState(reason));
263 }
264 
LogRemoteNameRequestCompletion(const RawAddress & raw_address,tHCI_STATUS hci_status)265 void LogRemoteNameRequestCompletion(const RawAddress& raw_address, tHCI_STATUS hci_status) {
266   hci::Address address = bluetooth::ToGdAddress(raw_address);
267   bluetooth::os::LogMetricBluetoothEvent(
268           address, EventType::REMOTE_NAME_REQUEST,
269           MapHCIStatusToState(hci_status));
270 }
271 
LogAclDisconnectionEvent(const hci::Address & address,ErrorCode reason,bool is_locally_initiated)272 void LogAclDisconnectionEvent(const hci::Address& address, ErrorCode reason,
273                               bool is_locally_initiated) {
274   bluetooth::os::LogMetricBluetoothEvent(address,
275                                          is_locally_initiated
276                                                  ? EventType::ACL_DISCONNECTION_INITIATOR
277                                                  : EventType::ACL_DISCONNECTION_RESPONDER,
278                                          MapErrorCodeToState(reason));
279 }
280 
LogAclAfterRemoteNameRequest(const RawAddress & raw_address,tBTM_STATUS status)281 void LogAclAfterRemoteNameRequest(const RawAddress& raw_address, tBTM_STATUS status) {
282   hci::Address address = bluetooth::ToGdAddress(raw_address);
283 
284   switch (status) {
285     case tBTM_STATUS::BTM_SUCCESS:
286       bluetooth::os::LogMetricBluetoothEvent(address, EventType::ACL_CONNECTION_INITIATOR,
287                                              State::ALREADY_CONNECTED);
288       break;
289     case tBTM_STATUS::BTM_NO_RESOURCES:
290       bluetooth::os::LogMetricBluetoothEvent(
291               address, EventType::ACL_CONNECTION_INITIATOR,
292               MapErrorCodeToState(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES));
293       break;
294     default:
295       break;
296   }
297 }
298 
LogAuthenticationComplete(const RawAddress & raw_address,tHCI_STATUS hci_status)299 void LogAuthenticationComplete(const RawAddress& raw_address, tHCI_STATUS hci_status) {
300   hci::Address address = bluetooth::ToGdAddress(raw_address);
301   bluetooth::os::LogMetricBluetoothEvent(address,
302                                          hci_status == tHCI_STATUS::HCI_SUCCESS
303                                                  ? EventType::AUTHENTICATION_COMPLETE
304                                                  : EventType::AUTHENTICATION_COMPLETE_FAIL,
305                                          MapHCIStatusToState(hci_status));
306 }
307 
LogSDPComplete(const RawAddress & raw_address,tBTA_STATUS status)308 void LogSDPComplete(const RawAddress& raw_address, tBTA_STATUS status) {
309   hci::Address address = bluetooth::ToGdAddress(raw_address);
310   bluetooth::os::LogMetricBluetoothEvent(
311           address, EventType::SERVICE_DISCOVERY,
312           status == tBTA_STATUS::BTA_SUCCESS ? State::SUCCESS : State::FAIL);
313 }
314 
LogLeAclCompletionEvent(const hci::Address & address,hci::ErrorCode reason,bool is_locally_initiated)315 void LogLeAclCompletionEvent(const hci::Address& address, hci::ErrorCode reason,
316                              bool is_locally_initiated) {
317   bluetooth::os::LogMetricBluetoothEvent(address,
318                                          is_locally_initiated
319                                                  ? EventType::LE_ACL_CONNECTION_INITIATOR
320                                                  : EventType::LE_ACL_CONNECTION_RESPONDER,
321                                          MapErrorCodeToState(reason));
322 }
323 
LogLePairingFail(const RawAddress & raw_address,uint8_t failure_reason,bool is_outgoing)324 void LogLePairingFail(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing) {
325   hci::Address address = bluetooth::ToGdAddress(raw_address);
326   bluetooth::os::LogMetricBluetoothEvent(
327           address, is_outgoing ? EventType::SMP_PAIRING_OUTGOING : EventType::SMP_PAIRING_INCOMING,
328           MapSmpStatusCodeToState(static_cast<tSMP_STATUS>(failure_reason)));
329 }
330 
331 }  // namespace metrics
332 }  // namespace bluetooth
333