diff options
author | 2025-02-03 15:09:59 -0800 | |
---|---|---|
committer | 2025-02-20 13:26:36 -0800 | |
commit | 0503ef80d9d1f90c6ed28cda7dae07ec62706a9b (patch) | |
tree | 06bb0068c6f70775b1a364010b1fe542bf94b738 | |
parent | e7e402ea4f4580bc2a116b22ebd93fa7ae4e2e31 (diff) |
RFCOMM metrics V2: Add metrics functions
- Collect metrics when sdp fails for HFP and RFCOMM
- Collect metrics when port creation fails for HFP and RFCOMM
- Collect metrics when port closes
Bug: 374989690
Test: m com.android.bt
Flag: EXEMPT metrics no-op
Change-Id: Ie2de6f0305afad58ab7d2cd7fdcf988c21649a28
-rw-r--r-- | system/bta/include/bta_rfcomm_metrics.h | 28 | ||||
-rw-r--r-- | system/bta/rfcomm/bta_rfcomm_metrics.cc | 152 | ||||
-rw-r--r-- | system/gd/os/android/metrics.cc | 38 | ||||
-rw-r--r-- | system/gd/os/chromeos/metrics.cc | 10 | ||||
-rw-r--r-- | system/gd/os/host/metrics.cc | 10 | ||||
-rw-r--r-- | system/gd/os/linux/metrics.cc | 9 | ||||
-rw-r--r-- | system/gd/os/metrics.h | 27 | ||||
-rw-r--r-- | system/main/shim/metrics_api.cc | 14 | ||||
-rw-r--r-- | system/main/shim/metrics_api.h | 19 | ||||
-rw-r--r-- | system/stack/include/rfc_metrics.h | 21 | ||||
-rw-r--r-- | system/stack/rfcomm/rfc_metrics.cc | 176 | ||||
-rw-r--r-- | system/test/mock/mock_main_shim_metrics_api.cc | 13 | ||||
-rw-r--r-- | system/test/mock/mock_main_shim_metrics_api.h | 37 |
13 files changed, 554 insertions, 0 deletions
diff --git a/system/bta/include/bta_rfcomm_metrics.h b/system/bta/include/bta_rfcomm_metrics.h new file mode 100644 index 0000000000..0db35f8ba4 --- /dev/null +++ b/system/bta/include/bta_rfcomm_metrics.h @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "bta_jv_api.h" +#include "types/raw_address.h" + +void bta_collect_rfc_metrics_after_sdp_fail(tBTA_JV_STATUS sdp_status, RawAddress addr, int app_uid, + int security, bool is_server, uint64_t sdp_duration); + +void bta_collect_rfc_metrics_after_port_fail(tPORT_RESULT port_result, bool sdp_initiated, + tBTA_JV_STATUS sdp_status, RawAddress addr, + int app_uid, int security, bool is_server, + uint64_t sdp_duration_ms); diff --git a/system/bta/rfcomm/bta_rfcomm_metrics.cc b/system/bta/rfcomm/bta_rfcomm_metrics.cc new file mode 100644 index 0000000000..5cbae01471 --- /dev/null +++ b/system/bta/rfcomm/bta_rfcomm_metrics.cc @@ -0,0 +1,152 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "bta_rfcomm_metrics" + +#include "bta_rfcomm_metrics.h" + +#include <bluetooth/log.h> +#include <frameworks/proto_logging/stats/enums/bluetooth/rfcomm/enums.pb.h> + +#include "bta_sec_api.h" +#include "main/shim/metrics_api.h" +#include "stack/include/btm_sec_api_types.h" + +using namespace bluetooth; + +using namespace android::bluetooth; +using namespace android::bluetooth::rfcomm; + +static BtaStatus toStatus(tBTA_JV_STATUS status); +static SocketConnectionSecurity toSecurity(int security); +static PortResult toPortResult(tPORT_RESULT result); + +// logged if SDP result is either FAILED or BUSY +void bta_collect_rfc_metrics_after_sdp_fail(tBTA_JV_STATUS sdp_status, RawAddress addr, int app_uid, + int security, bool is_server, + uint64_t sdp_duration_ms) { + // We only call this function in the case where we started (and failed) sdp + bool sdp_initiated = true; + + // We didn't make it to the stage of making a port, so assign default values for these fields + PortResult close_reason = PortResult::PORT_RESULT_UNDEFINED; + RfcommPortState state_prior = RfcommPortState::PORT_STATE_UNKNOWN; + RfcommPortEvent last_event = RfcommPortEvent::PORT_EVENT_UNKNOWN; + int open_duration_ms = 0; + + shim::LogMetricRfcommConnectionAtClose( + addr, close_reason, toSecurity(security), last_event, state_prior, open_duration_ms, + app_uid, toStatus(sdp_status), is_server, sdp_initiated, sdp_duration_ms); +} + +void bta_collect_rfc_metrics_after_port_fail(tPORT_RESULT port_result, bool sdp_initiated, + tBTA_JV_STATUS sdp_status, RawAddress addr, + int app_uid, int security, bool is_server, + uint64_t sdp_duration_ms) { + BtaStatus reported_status; + if (sdp_status == tBTA_JV_STATUS::SUCCESS && !sdp_initiated) { + reported_status = BtaStatus::BTA_STATUS_UNKNOWN; + } else { + reported_status = toStatus(sdp_status); + } + RfcommPortState state_prior = RfcommPortState::PORT_STATE_UNKNOWN; + RfcommPortEvent last_event = RfcommPortEvent::PORT_EVENT_UNKNOWN; + int open_duration_ms = 0; + + shim::LogMetricRfcommConnectionAtClose( + addr, toPortResult(port_result), toSecurity(security), last_event, state_prior, + open_duration_ms, app_uid, reported_status, is_server, sdp_initiated, sdp_duration_ms); +} + +static BtaStatus toStatus(tBTA_JV_STATUS status) { + switch (status) { + case tBTA_JV_STATUS::SUCCESS: + return BtaStatus::BTA_STATUS_SUCCESS; + case tBTA_JV_STATUS::FAILURE: + return BtaStatus::BTA_STATUS_FAILURE; + case tBTA_JV_STATUS::BUSY: + return BtaStatus::BTA_STATUS_BUSY; + } + return BtaStatus::BTA_STATUS_UNKNOWN; +} + +static SocketConnectionSecurity toSecurity(int security) { + if ((security == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) || + (security == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) || + (security == (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT))) { + return SocketConnectionSecurity::SOCKET_SECURITY_SECURE; + } else if (security == BTM_SEC_NONE) { + return SocketConnectionSecurity::SOCKET_SECURITY_INSECURE; + } + return SocketConnectionSecurity::SOCKET_SECURITY_UNKNOWN; +} + +static PortResult toPortResult(tPORT_RESULT result) { + switch (result) { + case PORT_SUCCESS: + return PortResult::PORT_RESULT_SUCCESS; + case PORT_UNKNOWN_ERROR: + return PortResult::PORT_RESULT_UNKNOWN_ERROR; + case PORT_ALREADY_OPENED: + return PortResult::PORT_RESULT_ALREADY_OPENED; + case PORT_CMD_PENDING: + return PortResult::PORT_RESULT_CMD_PENDING; + case PORT_APP_NOT_REGISTERED: + return PortResult::PORT_RESULT_APP_NOT_REGISTERED; + case PORT_NO_MEM: + return PortResult::PORT_RESULT_NO_MEM; + case PORT_NO_RESOURCES: + return PortResult::PORT_RESULT_NO_RESOURCES; + case PORT_BAD_BD_ADDR: + return PortResult::PORT_RESULT_BAD_BD_ADDR; + case PORT_BAD_HANDLE: + return PortResult::PORT_RESULT_BAD_HANDLE; + case PORT_NOT_OPENED: + return PortResult::PORT_RESULT_NOT_OPENED; + case PORT_LINE_ERR: + return PortResult::PORT_RESULT_LINE_ERR; + case PORT_START_FAILED: + return PortResult::PORT_RESULT_START_FAILED; + case PORT_PAR_NEG_FAILED: + return PortResult::PORT_RESULT_PAR_NEG_FAILED; + case PORT_PORT_NEG_FAILED: + return PortResult::PORT_RESULT_PORT_NEG_FAILED; + case PORT_SEC_FAILED: + return PortResult::PORT_RESULT_SEC_FAILED; + case PORT_PEER_CONNECTION_FAILED: + return PortResult::PORT_RESULT_PEER_CONNECTION_FAILED; + case PORT_PEER_FAILED: + return PortResult::PORT_RESULT_PEER_FAILED; + case PORT_PEER_TIMEOUT: + return PortResult::PORT_RESULT_PEER_TIMEOUT; + case PORT_CLOSED: + return PortResult::PORT_RESULT_CLOSED; + case PORT_TX_FULL: + return PortResult::PORT_RESULT_TX_FULL; + case PORT_LOCAL_CLOSED: + return PortResult::PORT_RESULT_LOCAL_CLOSED; + case PORT_LOCAL_TIMEOUT: + return PortResult::PORT_RESULT_LOCAL_TIMEOUT; + case PORT_TX_QUEUE_DISABLED: + return PortResult::PORT_RESULT_TX_QUEUE_DISABLED; + case PORT_PAGE_TIMEOUT: + return PortResult::PORT_RESULT_PAGE_TIMEOUT; + case PORT_INVALID_SCN: + return PortResult::PORT_RESULT_INVALID_SCN; + case PORT_ERR_MAX: + return PortResult::PORT_RESULT_ERR_MAX; + } + return PortResult::PORT_RESULT_UNDEFINED; +} diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index 1a899062cd..ddb9d826f1 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -30,6 +30,7 @@ #include "common/strings.h" #include "hardware/bt_av.h" #include "hci/hci_packets.h" +#include "main/shim/helpers.h" namespace std { template <> @@ -51,6 +52,20 @@ template <> struct formatter<android::bluetooth::EventType> : enum_formatter<android::bluetooth::EventType> {}; template <> struct formatter<android::bluetooth::State> : enum_formatter<android::bluetooth::State> {}; +template <> +struct formatter<android::bluetooth::rfcomm::PortResult> + : enum_formatter<android::bluetooth::rfcomm::PortResult> {}; +template <> +struct formatter<android::bluetooth::rfcomm::RfcommPortState> + : enum_formatter<android::bluetooth::rfcomm::RfcommPortState> {}; +template <> +struct formatter<android::bluetooth::rfcomm::RfcommPortEvent> + : enum_formatter<android::bluetooth::rfcomm::RfcommPortEvent> {}; +template <> +struct formatter<android::bluetooth::rfcomm::SocketConnectionSecurity> + : enum_formatter<android::bluetooth::rfcomm::SocketConnectionSecurity> {}; +template <> +struct formatter<android::bluetooth::BtaStatus> : enum_formatter<android::bluetooth::BtaStatus> {}; } // namespace std namespace bluetooth { @@ -478,5 +493,28 @@ void LogMetricBluetoothEvent(const Address& address, android::bluetooth::EventTy } } +void LogMetricRfcommConnectionAtClose(const Address& address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, + android::bluetooth::BtaStatus sdp_status, bool is_server, + bool sdp_initiated, int32_t sdp_duration_ms) { + int metric_id = 0; + if (address.IsEmpty()) { + log::warn("Failed to upload - Address is empty"); + return; + } + metric_id = MetricIdManager::GetInstance().AllocateId(address); + int ret = stats_write(BLUETOOTH_RFCOMM_CONNECTION_REPORTED_AT_CLOSE, close_reason, security, + last_event, previous_state, open_duration_ms, uid, metric_id, sdp_status, + is_server, sdp_initiated, sdp_duration_ms); + if (ret < 0) { + log::warn("Failed to log RFCOMM Connection metric for uid {}, close reason {}", uid, + close_reason); + } +} + } // namespace os } // namespace bluetooth diff --git a/system/gd/os/chromeos/metrics.cc b/system/gd/os/chromeos/metrics.cc index c5b33a4fce..70258d335a 100644 --- a/system/gd/os/chromeos/metrics.cc +++ b/system/gd/os/chromeos/metrics.cc @@ -203,5 +203,15 @@ void LogMetricBluetoothLEConnection(os::LEConnectionSessionOptions /* session_op void LogMetricBluetoothEvent(const Address& address, android::bluetooth::EventType event_type, android::bluetooth::State state) {} + +void LogMetricRfcommConnectionAtClose( + const Address& /* raw_address */, android::bluetooth::rfcomm::PortResult /* close_reason */, + android::bluetooth::rfcomm::SocketConnectionSecurity /* security */, + android::bluetooth::rfcomm::RfcommPortEvent /* last_event */, + android::bluetooth::rfcomm::RfcommPortState /* previous_state */, + int32_t /* open_duration_ms */, int32_t /* uid */, + android::bluetooth::BtaStatus /* sdp_status */, bool /* is_server */, + bool /* sdp_initiated */, int32_t /* sdp_duration_ms */) {} + } // namespace os } // namespace bluetooth diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc index a019033348..61734e6a81 100644 --- a/system/gd/os/host/metrics.cc +++ b/system/gd/os/host/metrics.cc @@ -124,5 +124,15 @@ void LogMetricBluetoothLEConnection(os::LEConnectionSessionOptions /* session_op void LogMetricBluetoothEvent(const Address& /* address */, android::bluetooth::EventType /* event type */, android::bluetooth::State /* state */) {} + +void LogMetricRfcommConnectionAtClose( + const Address& /* raw_address */, android::bluetooth::rfcomm::PortResult /* close_reason */, + android::bluetooth::rfcomm::SocketConnectionSecurity /* security */, + android::bluetooth::rfcomm::RfcommPortEvent /* last_event */, + android::bluetooth::rfcomm::RfcommPortState /* previous_state */, + int32_t /* open_duration_ms */, int32_t /* uid */, + android::bluetooth::BtaStatus /* sdp_status */, bool /* is_server */, + bool /* sdp_initiated */, int32_t /* sdp_duration_ms */) {} + } // namespace os } // namespace bluetooth diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc index c5e38493da..45fca1f4ee 100644 --- a/system/gd/os/linux/metrics.cc +++ b/system/gd/os/linux/metrics.cc @@ -108,6 +108,15 @@ void LogMetricBluetoothCodePathCounterMetrics(int32_t key, int64_t count) {} void LogMetricBluetoothLEConnection(os::LEConnectionSessionOptions /* session_options */) {} +void LogMetricRfcommConnectionAtClose(const Address& raw_address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, + android::bluetooth::BtaStatus sdp_status, bool is_server, + bool sdp_initiated, int32_t sdp_duration_ms) {} + void LogMetricBluetoothEvent(const Address& address, android::bluetooth::EventType event_type, android::bluetooth::State state) {} } // namespace os diff --git a/system/gd/os/metrics.h b/system/gd/os/metrics.h index 7d89483754..9f372b25af 100644 --- a/system/gd/os/metrics.h +++ b/system/gd/os/metrics.h @@ -21,10 +21,12 @@ #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h> #include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h> #include <frameworks/proto_logging/stats/enums/bluetooth/le/enums.pb.h> +#include <frameworks/proto_logging/stats/enums/bluetooth/rfcomm/enums.pb.h> #include <vector> #include "hci/address.h" +#include "types/raw_address.h" namespace bluetooth { @@ -346,6 +348,31 @@ void LogMetricBluetoothLEConnection(os::LEConnectionSessionOptions session_optio */ void LogMetricBluetoothEvent(const hci::Address& address, android::bluetooth::EventType event_type, android::bluetooth::State state); + +/** + * Logs an RFCOMM connection when an RFCOMM port closes + * + * @param address address of the peer device + * @param close_reason reason that the port was closed + * @param security security level of the connection + * @param last_event event processed prior to "CLOSED" + * @param previous_state state prior to "CLOSED" + * @param open_duration_ms that the socket was opened, 0 if connection failed + * @param uid UID of the app that called connect + * @param sdp_status status code for sdp + * @param is_server true if device is server + * @param sdp_initiated true if sdp started for thie connection + * @param sdp_duration_ms duration of sdp, 0 if it didn't happen + */ +void LogMetricRfcommConnectionAtClose(const hci::Address& address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, + android::bluetooth::BtaStatus sdp_status, bool is_server, + bool sdp_initiated, int32_t sdp_duration_ms); + } // namespace os // } // namespace bluetooth diff --git a/system/main/shim/metrics_api.cc b/system/main/shim/metrics_api.cc index 58b99b8831..6d2b317150 100644 --- a/system/main/shim/metrics_api.cc +++ b/system/main/shim/metrics_api.cc @@ -187,6 +187,20 @@ void LogMetricLeConnectionCompletion(hci::Address address, hci::ErrorCode reason bluetooth::metrics::LogLeAclCompletionEvent(address, reason, is_locally_initiated); } +void LogMetricRfcommConnectionAtClose(const RawAddress& raw_address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, + android::bluetooth::BtaStatus sdp_status, bool is_server, + bool sdp_initiated, int32_t sdp_duration_ms) { + Address address = bluetooth::ToGdAddress(raw_address); + bluetooth::os::LogMetricRfcommConnectionAtClose(address, close_reason, security, last_event, + previous_state, open_duration_ms, uid, sdp_status, + is_server, sdp_initiated, sdp_duration_ms); +} + bool CountCounterMetrics(int32_t key, int64_t count) { auto counter_metrics = GetCounterMetrics(); if (counter_metrics == nullptr) { diff --git a/system/main/shim/metrics_api.h b/system/main/shim/metrics_api.h index 6c539d1d1d..a2cd12cf9b 100644 --- a/system/main/shim/metrics_api.h +++ b/system/main/shim/metrics_api.h @@ -290,6 +290,25 @@ void LogMetricLeConnectionLifecycle(hci::Address address, bool is_connect, bool */ void LogMetricLeConnectionCompletion(hci::Address address, hci::ErrorCode reason, bool is_locally_initiated); +/** + * Logs an RFCOMM connection when an RFCOMM port closes + * + * @param address address of peer device + * @param close_reason reason that the port was closed + * @param security security level of the connection + * @param second_previous_state two states prior to "CLOSED" + * @param previous_state state prior to "CLOSED" + * @param duration_ms that the socket was opened, 0 if connection failed + * @param uid UID of the app that called connect + */ +void LogMetricRfcommConnectionAtClose(const RawAddress& address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, + android::bluetooth::BtaStatus sdp_status, bool is_server, + bool sdp_initiated, int32_t sdp_duration_ms); bool CountCounterMetrics(int32_t key, int64_t count); diff --git a/system/stack/include/rfc_metrics.h b/system/stack/include/rfc_metrics.h new file mode 100644 index 0000000000..66d73ec8d8 --- /dev/null +++ b/system/stack/include/rfc_metrics.h @@ -0,0 +1,21 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "stack/rfcomm/port_int.h" + +void port_collect_attempt_metrics(tPORT* p_port); diff --git a/system/stack/rfcomm/rfc_metrics.cc b/system/stack/rfcomm/rfc_metrics.cc new file mode 100644 index 0000000000..13f6ad2bdd --- /dev/null +++ b/system/stack/rfcomm/rfc_metrics.cc @@ -0,0 +1,176 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "rfc_metrics" + +#include "../include/rfc_metrics.h" + +#include <bluetooth/log.h> +#include <frameworks/proto_logging/stats/enums/bluetooth/rfcomm/enums.pb.h> + +#include "bta/include/bta_jv_api.h" +#include "common/time_util.h" +#include "main/shim/metrics_api.h" +#include "stack/btm/security_device_record.h" +#include "stack/include/btm_sec_api_types.h" +#include "stack/include/port_api.h" +#include "stack/rfcomm/port_int.h" +#include "stack/rfcomm/rfc_event.h" +#include "stack/rfcomm/rfc_state.h" +#include "types/raw_address.h" + +using namespace bluetooth; + +using namespace android::bluetooth; +using namespace android::bluetooth::rfcomm; + +static SocketConnectionSecurity toSecurity(uint16_t sec_mask); +static PortResult toPortResult(tPORT_RESULT result); +static RfcommPortState toPortState(tRFC_PORT_STATE state); +static RfcommPortEvent toPortEvent(tRFC_PORT_EVENT event); + +void port_collect_attempt_metrics(tPORT* p_port) { + bool is_server = p_port->is_server; + bool sdp_initiated = (p_port->sdp_duration_ms > 0); + // If we're calling this metrics function, SDP completed with no problems + BtaStatus sdp_status = sdp_initiated ? BTA_STATUS_SUCCESS : BTA_STATUS_UNKNOWN; + RfcommPortSm sm_cb = p_port->rfc.sm_cb; + log::assert_that(sm_cb.state == RFC_STATE_CLOSED, "Assert failed: Port not closed"); + uint64_t open_duration_ms = (sm_cb.close_timestamp - sm_cb.open_timestamp) / 1000; + + shim::LogMetricRfcommConnectionAtClose( + p_port->bd_addr, toPortResult(sm_cb.close_reason), toSecurity(p_port->sec_mask), + toPortEvent(sm_cb.last_event), toPortState(sm_cb.state_prior), + static_cast<int32_t>(open_duration_ms), static_cast<int32_t>(p_port->app_uid), sdp_status, + is_server, sdp_initiated, static_cast<int32_t>(p_port->sdp_duration_ms)); +} + +static SocketConnectionSecurity toSecurity(uint16_t sec_mask) { + if (((sec_mask & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) || + ((sec_mask & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT))) { + return SocketConnectionSecurity::SOCKET_SECURITY_SECURE; + } else if (((sec_mask & BTM_SEC_IN_FLAGS) == (BTM_SEC_NONE)) || + ((sec_mask & BTM_SEC_OUT_FLAGS) == (BTM_SEC_NONE))) { + return SocketConnectionSecurity::SOCKET_SECURITY_INSECURE; + } + + return SocketConnectionSecurity::SOCKET_SECURITY_UNKNOWN; +} + +static PortResult toPortResult(tPORT_RESULT result) { + switch (result) { + case PORT_SUCCESS: + return PortResult::PORT_RESULT_SUCCESS; + case PORT_UNKNOWN_ERROR: + return PortResult::PORT_RESULT_UNKNOWN_ERROR; + case PORT_ALREADY_OPENED: + return PortResult::PORT_RESULT_ALREADY_OPENED; + case PORT_CMD_PENDING: + return PortResult::PORT_RESULT_CMD_PENDING; + case PORT_APP_NOT_REGISTERED: + return PortResult::PORT_RESULT_APP_NOT_REGISTERED; + case PORT_NO_MEM: + return PortResult::PORT_RESULT_NO_MEM; + case PORT_NO_RESOURCES: + return PortResult::PORT_RESULT_NO_RESOURCES; + case PORT_BAD_BD_ADDR: + return PortResult::PORT_RESULT_BAD_BD_ADDR; + case PORT_BAD_HANDLE: + return PortResult::PORT_RESULT_BAD_HANDLE; + case PORT_NOT_OPENED: + return PortResult::PORT_RESULT_NOT_OPENED; + case PORT_LINE_ERR: + return PortResult::PORT_RESULT_LINE_ERR; + case PORT_START_FAILED: + return PortResult::PORT_RESULT_START_FAILED; + case PORT_PAR_NEG_FAILED: + return PortResult::PORT_RESULT_PAR_NEG_FAILED; + case PORT_PORT_NEG_FAILED: + return PortResult::PORT_RESULT_PORT_NEG_FAILED; + case PORT_SEC_FAILED: + return PortResult::PORT_RESULT_SEC_FAILED; + case PORT_PEER_CONNECTION_FAILED: + return PortResult::PORT_RESULT_PEER_CONNECTION_FAILED; + case PORT_PEER_FAILED: + return PortResult::PORT_RESULT_PEER_FAILED; + case PORT_PEER_TIMEOUT: + return PortResult::PORT_RESULT_PEER_TIMEOUT; + case PORT_CLOSED: + return PortResult::PORT_RESULT_CLOSED; + case PORT_TX_FULL: + return PortResult::PORT_RESULT_TX_FULL; + case PORT_LOCAL_CLOSED: + return PortResult::PORT_RESULT_LOCAL_CLOSED; + case PORT_LOCAL_TIMEOUT: + return PortResult::PORT_RESULT_LOCAL_TIMEOUT; + case PORT_TX_QUEUE_DISABLED: + return PortResult::PORT_RESULT_TX_QUEUE_DISABLED; + case PORT_PAGE_TIMEOUT: + return PortResult::PORT_RESULT_PAGE_TIMEOUT; + case PORT_INVALID_SCN: + return PortResult::PORT_RESULT_INVALID_SCN; + case PORT_ERR_MAX: + return PortResult::PORT_RESULT_ERR_MAX; + } + return PortResult::PORT_RESULT_UNDEFINED; +} + +static RfcommPortState toPortState(tRFC_PORT_STATE state) { + switch (state) { + case RFC_STATE_SABME_WAIT_UA: + return RfcommPortState::PORT_STATE_SABME_WAIT_UA; + case RFC_STATE_ORIG_WAIT_SEC_CHECK: + return RfcommPortState::PORT_STATE_ORIG_WAIT_SEC_CHECK; + case RFC_STATE_TERM_WAIT_SEC_CHECK: + return RfcommPortState::PORT_STATE_TERM_WAIT_SEC_CHECK; + case RFC_STATE_OPENED: + return RfcommPortState::PORT_STATE_OPENED; + case RFC_STATE_DISC_WAIT_UA: + return RfcommPortState::PORT_STATE_DISC_WAIT_UA; + case RFC_STATE_CLOSED: + return RfcommPortState::PORT_STATE_CLOSED; + } + return RfcommPortState::PORT_STATE_UNKNOWN; +} + +static RfcommPortEvent toPortEvent(tRFC_PORT_EVENT event) { + switch (event) { + case RFC_PORT_EVENT_SABME: + return RfcommPortEvent::PORT_EVENT_SABME; + case RFC_PORT_EVENT_UA: + return RfcommPortEvent::PORT_EVENT_UA; + case RFC_PORT_EVENT_DM: + return RfcommPortEvent::PORT_EVENT_DM; + case RFC_PORT_EVENT_DISC: + return RfcommPortEvent::PORT_EVENT_DISC; + case RFC_PORT_EVENT_UIH: + return RfcommPortEvent::PORT_EVENT_UIH; + case RFC_PORT_EVENT_TIMEOUT: + return RfcommPortEvent::PORT_EVENT_TIMEOUT; + case RFC_PORT_EVENT_OPEN: + return RfcommPortEvent::PORT_EVENT_OPEN; + case RFC_PORT_EVENT_ESTABLISH_RSP: + return RfcommPortEvent::PORT_EVENT_ESTABLISH_RSP; + case RFC_PORT_EVENT_CLOSE: + return RfcommPortEvent::PORT_EVENT_CLOSE; + case RFC_PORT_EVENT_CLEAR: + return RfcommPortEvent::PORT_EVENT_CLEAR; + case RFC_PORT_EVENT_DATA: + return RfcommPortEvent::PORT_EVENT_DATA; + case RFC_PORT_EVENT_SEC_COMPLETE: + return RfcommPortEvent::PORT_EVENT_SEC_COMPLETE; + } + return RfcommPortEvent::PORT_EVENT_UNKNOWN; +} diff --git a/system/test/mock/mock_main_shim_metrics_api.cc b/system/test/mock/mock_main_shim_metrics_api.cc index ac64150797..908f258205 100644 --- a/system/test/mock/mock_main_shim_metrics_api.cc +++ b/system/test/mock/mock_main_shim_metrics_api.cc @@ -59,6 +59,7 @@ struct LogMetricLeConnectionStatus LogMetricLeConnectionStatus; struct LogMetricLeDeviceInAcceptList LogMetricLeDeviceInAcceptList; struct LogMetricLeConnectionLifecycle LogMetricLeConnectionLifecycle; struct LogMetricLeConnectionCompletion LogMetricLeConnectionCompletion; +struct LogMetricRfcommConnectionAtClose LogMetricRfcommConnectionAtClose; } // namespace main_shim_metrics_api } // namespace mock @@ -215,4 +216,16 @@ void bluetooth::shim::LogMetricLeConnectionCompletion(bluetooth::hci::Address ad test::mock::main_shim_metrics_api::LogMetricLeConnectionCompletion(address, reason, is_locally_initiated); } +void bluetooth::shim::LogMetricRfcommConnectionAtClose( + const RawAddress& raw_address, android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, int32_t open_duration_ms, + int32_t uid, android::bluetooth::BtaStatus sdp_status, bool is_server, bool sdp_initiated, + int32_t sdp_duration_ms) { + inc_func_call_count(__func__); + test::mock::main_shim_metrics_api::LogMetricRfcommConnectionAtClose( + raw_address, close_reason, security, last_event, previous_state, open_duration_ms, uid, + sdp_status, is_server, sdp_initiated, sdp_duration_ms); +} // END mockcify generation diff --git a/system/test/mock/mock_main_shim_metrics_api.h b/system/test/mock/mock_main_shim_metrics_api.h index 6b8d8e5edf..7e8df3c3c8 100644 --- a/system/test/mock/mock_main_shim_metrics_api.h +++ b/system/test/mock/mock_main_shim_metrics_api.h @@ -367,6 +367,43 @@ struct LogMetricLeConnectionCompletion { }; extern struct LogMetricLeConnectionCompletion LogMetricLeConnectionCompletion; +// Name: LogMetricRfcommConnectionAtClose +// Params: const RawAddress& raw_address, android::bluetooth::rfcomm::PortResult close_reason, +// android::bluetooth::rfcomm::SocketConnectionSecurity security, +// android::bluetooth::rfcomm::RfcommPortEvent last_event, +// android::bluetooth::rfcomm::RfcommPortState previous_state, int32_t open_duration_ms, +// int32_t uid, android::bluetooth::BtaStatus sdp_status, bool is_server, +// bool sdp_initiated, int32_t sdp_duration_ms +// Returns: void +struct LogMetricRfcommConnectionAtClose { + std::function<void( + const RawAddress& raw_address, android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, int32_t open_duration_ms, + int32_t uid, android::bluetooth::BtaStatus sdp_status, bool is_server, bool sdp_initiated, + int32_t sdp_duration_ms)> + body{[](const RawAddress& /* raw_address */, + android::bluetooth::rfcomm::PortResult /* close_reason */, + android::bluetooth::rfcomm::SocketConnectionSecurity /* security */, + android::bluetooth::rfcomm::RfcommPortEvent /* last_event */, + android::bluetooth::rfcomm::RfcommPortState /* previous_state */, + int32_t /* open_duration_ms */, int32_t /* uid */, + android::bluetooth::BtaStatus /* sdp_status */, bool /* is_server */, + bool /* sdp_initiated */, int32_t /* sdp_duration_ms */) {}}; + void operator()(const RawAddress& raw_address, + android::bluetooth::rfcomm::PortResult close_reason, + android::bluetooth::rfcomm::SocketConnectionSecurity security, + android::bluetooth::rfcomm::RfcommPortEvent last_event, + android::bluetooth::rfcomm::RfcommPortState previous_state, + int32_t open_duration_ms, int32_t uid, android::bluetooth::BtaStatus sdp_status, + bool is_server, bool sdp_initiated, int32_t sdp_duration_ms) { + body(raw_address, close_reason, security, last_event, previous_state, open_duration_ms, uid, + sdp_status, is_server, sdp_initiated, sdp_duration_ms); + } +}; +extern struct LogMetricRfcommConnectionAtClose LogMetricRfcommConnectionAtClose; + } // namespace main_shim_metrics_api } // namespace mock } // namespace test |