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