From f3a8df5db3789bb3fdfe78b6a41083e108e7f6c1 Mon Sep 17 00:00:00 2001 From: Francis Tsui Date: Thu, 28 May 2026 10:08:10 -0700 Subject: [PATCH] Refactor AnalyticsRecorder into an abstract interface and decouple ClientProxy from logging protos. PiperOrigin-RevId: 922838021 --- Package.swift | 2 +- connections/implementation/BUILD | 13 +- connections/implementation/analytics/BUILD | 28 +- .../analytics/advertising_metadata_params.h | 5 +- .../analytics/analytics_recorder.cc | 1591 +--------------- .../analytics/analytics_recorder.h | 469 +---- .../analytics/analytics_recorder_impl.cc | 1643 +++++++++++++++++ .../analytics/analytics_recorder_impl.h | 459 +++++ ...est.cc => analytics_recorder_impl_test.cc} | 99 +- .../analytics/discovery_metadata_params.h | 5 +- .../analytics/operation_result_with_medium.h | 55 + .../implementation/base_endpoint_channel.cc | 13 +- .../implementation/base_endpoint_channel.h | 12 +- .../implementation/base_pcp_handler.cc | 97 +- connections/implementation/bwu_manager.cc | 7 +- .../implementation/bwu_manager_test.cc | 68 +- connections/implementation/client_proxy.cc | 19 +- connections/implementation/client_proxy.h | 8 +- .../implementation/encryption_runner_test.cc | 12 +- connections/implementation/endpoint_channel.h | 9 +- .../endpoint_channel_manager.cc | 10 +- .../implementation/endpoint_channel_manager.h | 11 +- .../endpoint_channel_manager_test.cc | 18 +- .../implementation/endpoint_manager.cc | 24 +- .../implementation/fake_endpoint_channel.h | 12 +- .../implementation/mock_endpoint_channel.h | 3 +- connections/implementation/payload_manager.cc | 13 +- 27 files changed, 2492 insertions(+), 2213 deletions(-) create mode 100644 connections/implementation/analytics/analytics_recorder_impl.cc create mode 100644 connections/implementation/analytics/analytics_recorder_impl.h rename connections/implementation/analytics/{analytics_recorder_test.cc => analytics_recorder_impl_test.cc} (97%) create mode 100644 connections/implementation/analytics/operation_result_with_medium.h diff --git a/Package.swift b/Package.swift index 27d9b761..50e2600f 100644 --- a/Package.swift +++ b/Package.swift @@ -368,7 +368,7 @@ let package = Package( "connections/implementation/payload_manager_test.cc", "connections/implementation/offline_frames_validator_test.cc", "connections/implementation/service_controller_router_test.cc", - "connections/implementation/analytics/analytics_recorder_test.cc", + "connections/implementation/analytics/analytics_recorder_impl_test.cc", "connections/implementation/analytics/throughput_recorder_test.cc", "connections/implementation/mediums/advertisements/data_element_test.cc", "connections/implementation/mediums/advertisements/dct_advertisement_test.cc", diff --git a/connections/implementation/BUILD b/connections/implementation/BUILD index b3bbee2d..c3723458 100644 --- a/connections/implementation/BUILD +++ b/connections/implementation/BUILD @@ -112,6 +112,7 @@ cc_library( deps = [ "//connections:core_types", "//connections/implementation/analytics", + "//connections/implementation/analytics:analytics_recorder_impl", "//connections/implementation/flags:connections_flags", "//connections/implementation/mediums/advertisements:dct_advertisement", "//connections/implementation/proto:offline_wire_formats_cc_proto", @@ -130,7 +131,6 @@ cc_library( "//internal/platform/implementation:comm", "//internal/platform/implementation:platform", "//internal/platform/implementation:types", - "//internal/proto/analytics:connections_log_cc_proto", "//proto:connections_enums_cc_proto", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", @@ -158,7 +158,6 @@ cc_library( deps = [ ":client_proxy", ":offline_frames", - ":types", "//connections:core_types", "//connections/implementation/analytics", "//connections/implementation/flags:connections_flags", @@ -167,7 +166,6 @@ cc_library( "//internal/platform:logging", "//internal/platform:types", "//internal/platform/implementation:types", - "//internal/proto/analytics:connections_log_cc_proto", "//proto:connections_enums_cc_proto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", @@ -263,7 +261,6 @@ cc_library( "//internal/platform/implementation:platform", "//internal/platform/implementation:types", "//internal/platform/implementation:wifi_utils", - "//internal/proto/analytics:connections_log_cc_proto", "//proto:connections_enums_cc_proto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:btree", @@ -341,22 +338,18 @@ cc_test( ":offline_frames", ":service_id_constants", "//connections:core_types", + "//connections/implementation/analytics", "//connections/implementation/flags:connections_flags", "//connections/implementation/mediums", "//internal/flags:nearby_flags", "//internal/platform:base", - "//internal/platform:logging", - "//internal/platform:test_util", "//internal/platform:types", - "//internal/platform/flags:platform_flags", "//internal/platform/implementation:platform", # build_cleaner: keep "//internal/platform/implementation/g3", # build_cleaner: keep - "//internal/proto/analytics:connections_log_cc_proto", "//proto:connections_enums_cc_proto", "@com_github_protobuf_matchers//protobuf-matchers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", - "@com_google_absl//absl/time", "@com_google_googletest//:gtest_main", ], ) @@ -556,13 +549,13 @@ cc_test( ":endpoint_channel", ":internal", ":offline_frames", + "//connections/implementation/analytics", "//connections/implementation/flags:connections_flags", "//internal/flags:nearby_flags", "//internal/platform:base", "//internal/platform:logging", "//internal/platform:types", "//internal/platform/implementation/g3", # build_cleaner: keep - "//internal/proto/analytics:connections_log_cc_proto", "//proto:connections_enums_cc_proto", "@com_github_protobuf_matchers//protobuf-matchers", "@com_google_absl//absl/strings", diff --git a/connections/implementation/analytics/BUILD b/connections/implementation/analytics/BUILD index f84377b4..0e47a452 100644 --- a/connections/implementation/analytics/BUILD +++ b/connections/implementation/analytics/BUILD @@ -26,10 +26,30 @@ cc_library( "analytics_recorder.h", "connection_attempt_metadata_params.h", "discovery_metadata_params.h", + "operation_result_with_medium.h", ], copts = ["-DCORE_ADAPTER_DLL"], visibility = ["//connections:__subpackages__"], deps = [ + "//connections:core_types", + "//internal/platform:error_code_recorder", + "//proto:connections_enums_cc_proto", + "@com_google_absl//absl/time", + ], +) + +cc_library( + name = "analytics_recorder_impl", + srcs = [ + "analytics_recorder_impl.cc", + ], + hdrs = [ + "analytics_recorder_impl.h", + ], + copts = ["-DCORE_ADAPTER_DLL"], + visibility = ["//connections/implementation:__pkg__"], + deps = [ + ":analytics", "//connections:core_types", "//internal/analytics:event_logger", "//internal/platform:error_code_recorder", @@ -40,11 +60,8 @@ cc_library( "//proto:connections_enums_cc_proto", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/container:btree", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/time", "@com_google_protobuf//:protobuf_lite", ], @@ -54,11 +71,12 @@ cc_test( name = "analytics_test", size = "small", srcs = [ - "analytics_recorder_test.cc", + "analytics_recorder_impl_test.cc", ], shard_count = 16, deps = [ ":analytics", + ":analytics_recorder_impl", "//connections:core_types", "//internal/analytics:mock_event_logger", "//internal/platform:base", diff --git a/connections/implementation/analytics/advertising_metadata_params.h b/connections/implementation/analytics/advertising_metadata_params.h index 2b3b3372..2b40864b 100644 --- a/connections/implementation/analytics/advertising_metadata_params.h +++ b/connections/implementation/analytics/advertising_metadata_params.h @@ -17,7 +17,7 @@ #include -#include "internal/proto/analytics/connections_log.pb.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" namespace nearby { @@ -26,8 +26,7 @@ struct AdvertisingMetadataParams { bool is_extended_advertisement_supported = false; int connected_ap_frequency = 0; bool is_nfc_available = false; - std::vector + std::vector operation_result_with_mediums = {}; }; diff --git a/connections/implementation/analytics/analytics_recorder.cc b/connections/implementation/analytics/analytics_recorder.cc index f91edcef..67649104 100644 --- a/connections/implementation/analytics/analytics_recorder.cc +++ b/connections/implementation/analytics/analytics_recorder.cc @@ -14,921 +14,35 @@ #include "connections/implementation/analytics/analytics_recorder.h" -#include -#include -#include #include #include -#include #include -#include "absl/algorithm/container.h" -#include "absl/container/btree_map.h" -#include "absl/strings/string_view.h" -#include "absl/time/time.h" #include "connections/implementation/analytics/advertising_metadata_params.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" #include "connections/implementation/analytics/discovery_metadata_params.h" -#include "connections/payload_type.h" -#include "connections/strategy.h" -#include "internal/analytics/event_logger.h" -#include "internal/platform/error_code_params.h" -#include "internal/platform/implementation/system_clock.h" -#include "internal/platform/logging.h" -#include "internal/platform/mutex_lock.h" -#include "internal/proto/analytics/connections_log.pb.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "proto/connections_enums.pb.h" -#include "google/protobuf/repeated_ptr_field.h" -namespace nearby { -namespace analytics { +namespace nearby::analytics { -namespace { -// const char kVersion_1_0_0[] = "v1.0.0"; -const char kVersion[] = "v1.5.0"; -constexpr absl::string_view kOnStartClientSession = "OnStartClientSession"; -const absl::Duration kConnectionTokenMaxLife = absl::Hours(24); - -using ::location::nearby::analytics::proto::ConnectionsLog; -using ::location::nearby::proto::connections::ACCEPTED; -using ::location::nearby::proto::connections::ADVERTISER; -using ::location::nearby::proto::connections::BandwidthUpgradeErrorStage; -using ::location::nearby::proto::connections::BandwidthUpgradeResult; -using ::location::nearby::proto::connections::BYTES; -using ::location::nearby::proto::connections::CLIENT_SESSION; -using ::location::nearby::proto::connections::CONNECTION_CLOSED; -using ::location::nearby::proto::connections::ConnectionAttemptDirection; -using ::location::nearby::proto::connections::ConnectionAttemptResult; -using ::location::nearby::proto::connections::ConnectionAttemptType; using ::location::nearby::proto::connections::ConnectionBand; -using ::location::nearby::proto::connections::ConnectionRequestResponse; -using ::location::nearby::proto::connections::ConnectionsStrategy; using ::location::nearby::proto::connections::ConnectionTechnology; -using ::location::nearby::proto::connections::DisconnectionReason; -using ::location::nearby::proto::connections::DISCOVERER; -using ::location::nearby::proto::connections::ERROR_CODE; -using ::location::nearby::proto::connections::EventType; -using ::location::nearby::proto::connections::FILE; -using ::location::nearby::proto::connections::IGNORED; -using ::location::nearby::proto::connections::INCOMING; -using ::location::nearby::proto::connections::INITIAL; using ::location::nearby::proto::connections::Medium; -using ::location::nearby::proto::connections::MOVED_TO_NEW_MEDIUM; -using ::location::nearby::proto::connections::NOT_SENT; -using ::location::nearby::proto::connections::OperationResultCategory; using ::location::nearby::proto::connections::OperationResultCode; -using ::location::nearby::proto::connections::OUTGOING; -using ::location::nearby::proto::connections::P2P_CLUSTER; -using ::location::nearby::proto::connections::P2P_POINT_TO_POINT; -using ::location::nearby::proto::connections::P2P_STAR; -using ::location::nearby::proto::connections::PayloadStatus; -using ::location::nearby::proto::connections::PayloadType; -using ::location::nearby::proto::connections::REJECTED; -using ::location::nearby::proto::connections::RESULT_SUCCESS; -using ::location::nearby::proto::connections::SessionRole; -using ::location::nearby::proto::connections::START_CLIENT_SESSION; -using ::location::nearby::proto::connections::START_STRATEGY_SESSION; -using ::location::nearby::proto::connections::STOP_CLIENT_SESSION; -using ::location::nearby::proto::connections::STOP_STRATEGY_SESSION; -using ::location::nearby::proto::connections::StopAdvertisingReason; -using ::location::nearby::proto::connections::StopDiscoveringReason; -using ::location::nearby::proto::connections::STREAM; -using ::location::nearby::proto::connections::UNFINISHED; -using ::location::nearby::proto::connections::UNFINISHED_ERROR; -using ::location::nearby::proto::connections::UNKNOWN_MEDIUM; -using ::location::nearby::proto::connections::UNKNOWN_PAYLOAD_TYPE; -using ::location::nearby::proto::connections::UNKNOWN_STRATEGY; -using ::location::nearby::proto::connections::UPGRADE_RESULT_SUCCESS; -using ::location::nearby::proto::connections::UPGRADE_SUCCESS; -using ::location::nearby::proto::connections::UPGRADE_UNFINISHED; -using ::location::nearby::proto::connections::UPGRADED; -using ::nearby::analytics::EventLogger; -using SafeDisconnectionResult = ::location::nearby::analytics::proto:: - ConnectionsLog::EstablishedConnection::SafeDisconnectionResult; - -OperationResultCategory ConvertToOperationResultCategory( - OperationResultCode result_code) { - if (result_code == OperationResultCode::DETAIL_SUCCESS) { - return OperationResultCategory::CATEGORY_SUCCESS; - } - // TODO(b/409865630): check later if we need to add back the dct error. - // Section of CATEGORY_DCT_ERROR, from 5000 to 5499 if (result_code - // >= OperationResultCode::DCT_ERROR_BLE_DISABLED) { - // return OperationResultCategory::CATEGORY_DCT_ERROR; - //} - - // Section of CATEGORY_NEARBY_ERROR, starting from 4500 to 4999 - if (result_code >= - OperationResultCode::NEARBY_BLE_ADVERTISEMENT_MAPPING_TO_MAC_ERROR) { - return OperationResultCategory::CATEGORY_NEARBY_ERROR; - } - // Section of CATEGORY_CONNECTIVITY_ERROR, starting from 3500 to 4499 - if (result_code >= - OperationResultCode::CONNECTIVITY_WIFI_AWARE_ATTACH_FAILURE) { - return OperationResultCategory::CATEGORY_CONNECTIVITY_ERROR; - } - // Section of CATEGORY_IO_ERROR, from 3000 to 3499 - if (result_code >= OperationResultCode::IO_FILE_OPENING_ERROR) { - return OperationResultCategory::CATEGORY_IO_ERROR; - } - // Section of CATEGORY_MISCELLANEOUS, from 2500 to 2999 - if (result_code >= - OperationResultCode::MISCELLEANEOUS_BLUETOOTH_MAC_ADDRESS_NULL) { - return OperationResultCategory::CATEGORY_MISCELLANEOUS; - } - // Section of CATEGORY_CLIENT_ERROR, from 2000 to 2499 - if (result_code >= - OperationResultCode:: - CLIENT_WIFI_DIRECT_ALREADY_HOSTING_DIRECT_GROUP_FOR_THIS_CLIENT) { - return OperationResultCategory::CATEGORY_CLIENT_ERROR; - } - // Section of CATEGORY_MEDIUM_UNAVAILABLE, from 1500 to 1999 - if (result_code >= OperationResultCode:: - MEDIUM_UNAVAILABLE_WIFI_AWARE_RESOURCE_NOT_AVAILABLE) { - return OperationResultCategory::CATEGORY_MEDIUM_UNAVAILABLE; - } - // Section of CATEGORY_DEVICE_STATE_ERROR, from 1000 to 1499 - if (result_code >= - OperationResultCode::DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS) { - return OperationResultCategory::CATEGORY_DEVICE_STATE_ERROR; - } - // Section of CATEGORY_CLIENT_CANCELLATION, from 500 to 999 - if (result_code >= - OperationResultCode::CLIENT_CANCELLATION_REMOTE_IN_CANCELED_STATE) { - return OperationResultCategory::CATEGORY_CLIENT_CANCELLATION; - } - // Clarify other non success cases as unknown - return OperationResultCategory::CATEGORY_UNKNOWN; -} -} // namespace - -AnalyticsRecorder::AnalyticsRecorder(EventLogger* event_logger) - : event_logger_(event_logger) { - VLOG(1) << "Start AnalyticsRecorder ctor event_logger_=" << event_logger_; - LogStartSession(); -} - -AnalyticsRecorder::~AnalyticsRecorder() = default; - -bool AnalyticsRecorder::IsSessionLogged() { - MutexLock lock(&mutex_); - return session_was_logged_; -} - -int AnalyticsRecorder::GetLatestUpdateIndexLocked( - const std::vector& list) { - int latest_update_index = 0; - for (const auto& operation_result_with_medium : list) { - if (operation_result_with_medium.update_index() > latest_update_index) { - latest_update_index = operation_result_with_medium.update_index(); - } - } - return latest_update_index; -} - -void AnalyticsRecorder::OnStartAdvertising( - connections::Strategy strategy, const std::vector& mediums, - AdvertisingMetadataParams* advertising_metadata_params) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStartAdvertising")) { - return; - } - if (!strategy.IsValid()) { - LOG(INFO) << "AnalyticsRecorder OnStartAdvertising with unknown " - "strategy, bail out."; - return; - } - // Initialize/update a StrategySession. - UpdateStrategySessionLocked(strategy, ADVERTISER); - - // Initialize and set a AdvertisingPhase. - started_advertising_phase_time_ = SystemClock::ElapsedRealtime(); - current_advertising_phase_ = - std::make_unique(); - absl::c_copy(mediums, RepeatedFieldBackInserter( - current_advertising_phase_->mutable_medium())); - // Set a AdvertisingMetadata. - AdvertisingMetadataParams default_params = {}; - if (advertising_metadata_params == nullptr) { - advertising_metadata_params = &default_params; - } - if (!advertising_metadata_params->operation_result_with_mediums.empty()) { - absl::c_copy(advertising_metadata_params->operation_result_with_mediums, - RepeatedFieldBackInserter( - current_advertising_phase_->mutable_adv_dis_result())); - } - auto* advertising_metadata = - current_advertising_phase_->mutable_advertising_metadata(); - advertising_metadata->set_supports_extended_ble_advertisements( - advertising_metadata_params->is_extended_advertisement_supported); - advertising_metadata->set_connected_ap_frequency( - advertising_metadata_params->connected_ap_frequency); - advertising_metadata->set_supports_nfc_technology( - advertising_metadata_params->is_nfc_available); -} - -void AnalyticsRecorder::OnStopAdvertising() { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStopAdvertising")) { - return; - } - RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ true); -} - -int AnalyticsRecorder::GetNextAdvertisingUpdateIndex() { - MutexLock lock(&mutex_); - - if (current_advertising_phase_ == nullptr) { - return 0; - } - return GetLatestUpdateIndexLocked( - std::vector( - current_advertising_phase_->adv_dis_result().begin(), - current_advertising_phase_->adv_dis_result().end())) + - 1; -} - -void AnalyticsRecorder::OnStartDiscovery( - connections::Strategy strategy, const std::vector& mediums, - DiscoveryMetadataParams* discovery_metadata_params) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStartDiscovery")) { - return; - } - if (!strategy.IsValid()) { - LOG(INFO) << "AnalyticsRecorder OnStartDiscovery unknown " - "strategy enter, bail out."; - return; - } - - // Initialize/update a StrategySession. - UpdateStrategySessionLocked(strategy, DISCOVERER); - - // Initialize and set a DiscoveryPhase. - started_discovery_phase_time_ = SystemClock::ElapsedRealtime(); - current_discovery_phase_ = std::make_unique(); - absl::c_copy(mediums, RepeatedFieldBackInserter( - current_discovery_phase_->mutable_medium())); - // Set a DiscoveryMetadata. - DiscoveryMetadataParams default_params = {}; - if (discovery_metadata_params == nullptr) { - discovery_metadata_params = &default_params; - } - if (!discovery_metadata_params->operation_result_with_mediums.empty()) { - absl::c_copy(discovery_metadata_params->operation_result_with_mediums, - RepeatedFieldBackInserter( - current_discovery_phase_->mutable_adv_dis_result())); - } - auto* discovery_metadata = - current_discovery_phase_->mutable_discovery_metadata(); - discovery_metadata->set_supports_extended_ble_advertisements( - discovery_metadata_params->is_extended_advertisement_supported); - discovery_metadata->set_connected_ap_frequency( - discovery_metadata_params->connected_ap_frequency); - discovery_metadata->set_supports_nfc_technology( - discovery_metadata_params->is_nfc_available); -} - -void AnalyticsRecorder::OnStopDiscovery() { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStopDiscovery")) { - return; - } - RecordDiscoveryPhaseDurationAndReasonLocked(/*on_stop=*/true); -} - -int AnalyticsRecorder::GetNextDiscoveryUpdateIndex() { - MutexLock lock(&mutex_); - if (current_discovery_phase_ == nullptr) { - return 0; - } - return GetLatestUpdateIndexLocked( - std::vector( - current_discovery_phase_->adv_dis_result().begin(), - current_discovery_phase_->adv_dis_result().end())) + - 1; -} - -void AnalyticsRecorder::OnStartedIncomingConnectionListening( - connections::Strategy strategy) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStartedIncomingConnectionListening")) { - return; - } - UpdateStrategySessionLocked(strategy, ADVERTISER); - if (started_advertising_phase_time_ == absl::InfinitePast()) { - started_advertising_phase_time_ = SystemClock::ElapsedRealtime(); - } -} - -void AnalyticsRecorder::OnStoppedIncomingConnectionListening() { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnStoppedIncomingConnectionListening")) { - return; - } - RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); -} - -void AnalyticsRecorder::OnEndpointFound(Medium medium) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnEndpointFound")) { - return; - } - if (current_discovery_phase_ == nullptr) { - LOG(INFO) << "Unable to record discovered endpoint due to null " - "current_discovery_phase_"; - return; - } - ConnectionsLog::DiscoveredEndpoint* discovered_endpoint = - current_discovery_phase_->add_discovered_endpoint(); - discovered_endpoint->set_medium(medium); - discovered_endpoint->set_latency_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_discovery_phase_time_)); -} - -void AnalyticsRecorder::OnRequestConnection( - const connections::Strategy& strategy, const std::string& endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("onRequestConnection")) { - return; - } - - UpdateStrategySessionLocked(strategy, DISCOVERER); - if (started_discovery_phase_time_ == absl::InfinitePast()) { - started_discovery_phase_time_ = SystemClock::ElapsedRealtime(); - } -} - -void AnalyticsRecorder::OnConnectionRequestReceived( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnConnectionRequestReceived")) { - return; - } - absl::Time current_time = SystemClock::ElapsedRealtime(); - auto connection_request = - std::make_unique(); - connection_request->set_duration_millis(absl::ToUnixMillis(current_time)); - connection_request->set_request_delay_millis(absl::ToInt64Milliseconds( - current_time - started_advertising_phase_time_)); - incoming_connection_requests_.insert( - {remote_endpoint_id, std::move(connection_request)}); -} - -void AnalyticsRecorder::OnConnectionRequestSent( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnConnectionRequestSent")) { - return; - } - absl::Time current_time = SystemClock::ElapsedRealtime(); - auto connection_request = - std::make_unique(); - connection_request->set_duration_millis(absl::ToUnixMillis(current_time)); - connection_request->set_request_delay_millis( - absl::ToInt64Milliseconds(current_time - started_discovery_phase_time_)); - outgoing_connection_requests_.insert( - {remote_endpoint_id, std::move(connection_request)}); -} - -void AnalyticsRecorder::OnRemoteEndpointAccepted( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnRemoteEndpointAccepted")) { - return; - } - RemoteEndpointRespondedLocked(remote_endpoint_id, ACCEPTED); -} - -void AnalyticsRecorder::OnLocalEndpointAccepted( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnLocalEndpointAccepted")) { - return; - } - LocalEndpointRespondedLocked(remote_endpoint_id, ACCEPTED); -} - -void AnalyticsRecorder::OnRemoteEndpointRejected( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnRemoteEndpointRejected")) { - return; - } - RemoteEndpointRespondedLocked(remote_endpoint_id, REJECTED); -} - -void AnalyticsRecorder::OnLocalEndpointRejected( - const std::string& remote_endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnLocalEndpointRejected")) { - return; - } - LocalEndpointRespondedLocked(remote_endpoint_id, REJECTED); -} - -void AnalyticsRecorder::OnIncomingConnectionAttempt( - ConnectionAttemptType type, Medium medium, ConnectionAttemptResult result, - absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnIncomingConnectionAttempt")) { - return; - } - if (current_strategy_session_ == nullptr) { - LOG(INFO) << "Unable to record incoming connection attempt due to " - "null current_strategy_session_"; - return; - } - - ConnectionAttemptMetadataParams default_params = {}; - if (connection_attempt_metadata_params == nullptr) { - connection_attempt_metadata_params = &default_params; - } - OnIncomingConnectionAttemptLocked(type, medium, result, duration, - connection_token, - connection_attempt_metadata_params); -} - -void AnalyticsRecorder::OnIncomingConnectionAttemptLocked( - location::nearby::proto::connections::ConnectionAttemptType type, - location::nearby::proto::connections::Medium medium, - location::nearby::proto::connections::ConnectionAttemptResult result, - absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { - auto* connection_attempt = - current_strategy_session_->add_connection_attempt(); - connection_attempt->set_duration_millis(absl::ToInt64Milliseconds(duration)); - connection_attempt->set_type(type); - connection_attempt->set_direction(INCOMING); - connection_attempt->set_medium(medium); - connection_attempt->set_attempt_result(result); - connection_attempt->set_connection_token(connection_token); - - auto* connection_attempt_metadata = - connection_attempt->mutable_connection_attempt_metadata(); - connection_attempt_metadata->set_technology( - connection_attempt_metadata_params->technology); - connection_attempt_metadata->set_band( - connection_attempt_metadata_params->band); - connection_attempt_metadata->set_frequency( - connection_attempt_metadata_params->frequency); - connection_attempt_metadata->set_network_operator( - connection_attempt_metadata_params->network_operator); - connection_attempt_metadata->set_country_code( - connection_attempt_metadata_params->country_code); - connection_attempt_metadata->set_frequency( - connection_attempt_metadata_params->frequency); - connection_attempt_metadata->set_is_tdls_used( - connection_attempt_metadata_params->is_tdls_used); - connection_attempt_metadata->set_wifi_hotspot_status( - connection_attempt_metadata_params->wifi_hotspot_enabled); - connection_attempt_metadata->set_try_counts( - connection_attempt_metadata_params->try_count); - connection_attempt_metadata->set_max_tx_speed( - connection_attempt_metadata_params->max_wifi_tx_speed); - connection_attempt_metadata->set_max_rx_speed( - connection_attempt_metadata_params->max_wifi_rx_speed); - connection_attempt_metadata->set_wifi_channel_width( - connection_attempt_metadata_params->channel_width); - - auto operation_result_proto = - std::make_unique(); - operation_result_proto->set_result_code( - connection_attempt_metadata_params->operation_result_code); - operation_result_proto->set_result_category(ConvertToOperationResultCategory( - connection_attempt_metadata_params->operation_result_code)); - connection_attempt->set_allocated_operation_result( - operation_result_proto.release()); -} - -void AnalyticsRecorder::OnOutgoingConnectionAttempt( - const std::string& remote_endpoint_id, ConnectionAttemptType type, - Medium medium, ConnectionAttemptResult result, absl::Duration duration, - const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnOutgoingConnectionAttempt")) { - return; - } - if (current_strategy_session_ == nullptr) { - LOG(INFO) << "Unable to record outgoing connection attempt due to " - "null current_strategy_session_"; - return; - } - - ConnectionAttemptMetadataParams default_params = {}; - if (connection_attempt_metadata_params == nullptr) { - connection_attempt_metadata_params = &default_params; - } - - // For the case of transfer a big file and the upgrades always failure, then - // there will have repeating upgrade attempt and cause many same attempt value - // be log. So add a method to skip. - if (ConnectionAttemptResultCodeExistedLocked( - medium, OUTGOING, connection_token, type, - connection_attempt_metadata_params->operation_result_code)) { - return; - } - - OnOutgoingConnectionAttemptLocked(remote_endpoint_id, type, medium, result, - duration, connection_token, - connection_attempt_metadata_params); -} - -void AnalyticsRecorder::OnOutgoingConnectionAttemptLocked( - const std::string& remote_endpoint_id, ConnectionAttemptType type, - Medium medium, ConnectionAttemptResult result, absl::Duration duration, - const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { - auto* connection_attempt = - current_strategy_session_->add_connection_attempt(); - connection_attempt->set_duration_millis(absl::ToInt64Milliseconds(duration)); - connection_attempt->set_type(type); - connection_attempt->set_direction(OUTGOING); - connection_attempt->set_medium(medium); - connection_attempt->set_attempt_result(result); - connection_attempt->set_connection_token(connection_token); - - auto* connection_attempt_metadata = - connection_attempt->mutable_connection_attempt_metadata(); - connection_attempt_metadata->set_technology( - connection_attempt_metadata_params->technology); - connection_attempt_metadata->set_band( - connection_attempt_metadata_params->band); - connection_attempt_metadata->set_frequency( - connection_attempt_metadata_params->frequency); - connection_attempt_metadata->set_network_operator( - connection_attempt_metadata_params->network_operator); - connection_attempt_metadata->set_country_code( - connection_attempt_metadata_params->country_code); - connection_attempt_metadata->set_frequency( - connection_attempt_metadata_params->frequency); - connection_attempt_metadata->set_is_tdls_used( - connection_attempt_metadata_params->is_tdls_used); - connection_attempt_metadata->set_wifi_hotspot_status( - connection_attempt_metadata_params->wifi_hotspot_enabled); - connection_attempt_metadata->set_try_counts( - connection_attempt_metadata_params->try_count); - connection_attempt_metadata->set_max_tx_speed( - connection_attempt_metadata_params->max_wifi_tx_speed); - connection_attempt_metadata->set_max_rx_speed( - connection_attempt_metadata_params->max_wifi_rx_speed); - connection_attempt_metadata->set_wifi_channel_width( - connection_attempt_metadata_params->channel_width); - - auto operation_result_proto = - std::make_unique(); - operation_result_proto->set_result_code( - connection_attempt_metadata_params->operation_result_code); - operation_result_proto->set_result_category(ConvertToOperationResultCategory( - connection_attempt_metadata_params->operation_result_code)); - connection_attempt->set_allocated_operation_result( - operation_result_proto.release()); - - if (type == INITIAL && result != RESULT_SUCCESS) { - auto it = outgoing_connection_requests_.find(remote_endpoint_id); - if (it != outgoing_connection_requests_.end()) { - // An outgoing, initial ConnectionAttempt has a corresponding - // ConnectionRequest that, since the ConnectionAttempt has failed, will - // never be delivered to the advertiser. - auto pair = outgoing_connection_requests_.extract(it); - std::unique_ptr& connection_request = - pair.mapped(); - connection_request->set_local_response(NOT_SENT); - connection_request->set_remote_response(NOT_SENT); - UpdateDiscovererConnectionRequestLocked(connection_request.get()); - } - } -} - -void AnalyticsRecorder::OnConnectionEstablished( - const std::string& endpoint_id, Medium medium, - const std::string& connection_token) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnConnectionEstablished")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it != active_connections_.end()) { - const std::unique_ptr& logical_connection = it->second; - logical_connection->PhysicalConnectionEstablished(medium, connection_token); - } else { - active_connections_.insert( - {endpoint_id, - std::make_unique(medium, connection_token)}); - } -} - -void AnalyticsRecorder::OnConnectionClosed(const std::string& endpoint_id, - Medium medium, - DisconnectionReason reason, - SafeDisconnectionResult result) { - MutexLock lock(&mutex_); - LOG(INFO) << __func__ - << ": OnConnectionClosed is called with endpoint_id:" << endpoint_id - << ", medium:" << Medium_Name(medium) - << ", reason:" << DisconnectionReason_Name(reason) - << ", result:" << result; - - if (!CanRecordAnalyticsLocked("OnConnectionClosed")) { - return; - } - - if (current_strategy_session_ == nullptr) { - VLOG(1) << "AnalyticsRecorder CanRecordAnalytics Unexpected call " - << __func__ << " since current_strategy_session_ is required."; - return; - } - - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->PhysicalConnectionClosed(medium, reason, result); - if (reason != UPGRADED) { - // Unless this is an upgraded connection, remove this from our active - // connections. Any future communication with an endpoint will need to be - // re-established with a new ConnectionRequest. - auto pair = active_connections_.extract(it); - std::unique_ptr& logical_connection = pair.mapped(); - - absl::c_copy( - logical_connection->GetEstablisedConnections(), - RepeatedFieldBackInserter( - current_strategy_session_->mutable_established_connection())); - } -} - -void AnalyticsRecorder::OnIncomingPayloadStarted( - const std::string& endpoint_id, std::int64_t payload_id, - connections::PayloadType type, std::int64_t total_size_bytes) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnIncomingPayloadStarted")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->IncomingPayloadStarted( - payload_id, PayloadTypeToProtoPayloadType(type), total_size_bytes); -} - -void AnalyticsRecorder::OnPayloadChunkReceived(const std::string& endpoint_id, - std::int64_t payload_id, - std::int64_t chunk_size_bytes) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnPayloadChunkReceived")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->ChunkReceived(payload_id, chunk_size_bytes); -} - -void AnalyticsRecorder::OnIncomingPayloadDone( - const std::string& endpoint_id, std::int64_t payload_id, - PayloadStatus status, OperationResultCode operation_result_code) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnIncomingPayloadDone")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->IncomingPayloadDone(payload_id, status, - operation_result_code); -} - -void AnalyticsRecorder::OnOutgoingPayloadStarted( - const std::vector& endpoint_ids, std::int64_t payload_id, - connections::PayloadType type, std::int64_t total_size_bytes) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnOutgoingPayloadStarted")) { - return; - } - for (const auto& endpoint_id : endpoint_ids) { - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - continue; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->OutgoingPayloadStarted( - payload_id, PayloadTypeToProtoPayloadType(type), total_size_bytes); - } -} - -void AnalyticsRecorder::OnPayloadChunkSent(const std::string& endpoint_id, - std::int64_t payload_id, - std::int64_t chunk_size_bytes) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnPayloadChunkSent")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - const std::unique_ptr& logical_connection = it->second; - logical_connection->ChunkSent(payload_id, chunk_size_bytes); -} - -void AnalyticsRecorder::OnOutgoingPayloadDone( - const std::string& endpoint_id, std::int64_t payload_id, - PayloadStatus status, OperationResultCode operation_result_code) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnOutgoingPayloadDone")) { - return; - } - auto it = active_connections_.find(endpoint_id); - if (it == active_connections_.end()) { - return; - } - - const std::unique_ptr& logical_connection = it->second; - logical_connection->OutgoingPayloadDone(payload_id, status, - operation_result_code); -} - -void AnalyticsRecorder::OnBandwidthUpgradeStarted( - const std::string& endpoint_id, Medium from_medium, Medium to_medium, - ConnectionAttemptDirection direction, const std::string& connection_token) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeStarted")) { - return; - } - auto bandwidth_upgrade_attempt = - std::make_unique(); - bandwidth_upgrade_attempt->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime())); - bandwidth_upgrade_attempt->set_from_medium(from_medium); - bandwidth_upgrade_attempt->set_to_medium(to_medium); - bandwidth_upgrade_attempt->set_direction(direction); - bandwidth_upgrade_attempt->set_connection_token(connection_token); - bandwidth_upgrade_attempts_.insert( - {endpoint_id, std::move(bandwidth_upgrade_attempt)}); -} - -void AnalyticsRecorder::UpdateBwUpgradeNetworkInfo( - const std::string& endpoint_id, int num_interfaces, - int num_ipv6_only_interfaces) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("UpdateBwUpgradeNetworkInfo")) { - return; - } - auto it = bandwidth_upgrade_attempts_.find(endpoint_id); - if (it == bandwidth_upgrade_attempts_.end()) { - return; - } - ConnectionsLog::BandwidthUpgradeAttempt* bandwidth_upgrade_attempt = - it->second.get(); - bandwidth_upgrade_attempt->set_num_interfaces(num_interfaces); - bandwidth_upgrade_attempt->set_num_ipv6_only_interfaces( - num_ipv6_only_interfaces); -} - -void AnalyticsRecorder::OnBandwidthUpgradeError( - const std::string& endpoint_id, BandwidthUpgradeResult result, - BandwidthUpgradeErrorStage error_stage, - OperationResultCode operation_result_code) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeError")) { - return; - } - // If the same records existed, drop this one. - if (EraseIfBandwidthUpgradeRecordExistedLocked( - endpoint_id, result, error_stage, operation_result_code)) { - return; - } - FinishUpgradeAttemptLocked(endpoint_id, result, error_stage, - operation_result_code); -} - -void AnalyticsRecorder::OnBandwidthUpgradeSuccess( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeSuccess")) { - return; - } - FinishUpgradeAttemptLocked(endpoint_id, UPGRADE_RESULT_SUCCESS, - UPGRADE_SUCCESS, - OperationResultCode::DETAIL_SUCCESS); -} - -void AnalyticsRecorder::OnErrorCode(const ErrorCodeParams& params) { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("OnErrorCode")) { - return; - } - auto error_code = std::make_unique(); - error_code->set_medium(params.medium); - error_code->set_event(params.event); - error_code->set_connection_token(params.connection_token); - error_code->set_description(params.description); - - if (params.is_common_error) { - error_code->set_common_error(params.common_error); - } else { - switch (params.event) { - case location::nearby::errorcode::proto::START_ADVERTISING: - error_code->set_start_advertising_error(params.start_advertising_error); - break; - case location::nearby::errorcode::proto::STOP_ADVERTISING: - error_code->set_stop_advertising_error(params.stop_advertising_error); - break; - case location::nearby::errorcode::proto:: - START_LISTENING_INCOMING_CONNECTION: - error_code->set_start_listening_incoming_connection_error( - params.start_listening_incoming_connection_error); - break; - case location::nearby::errorcode::proto:: - STOP_LISTENING_INCOMING_CONNECTION: - error_code->set_stop_listening_incoming_connection_error( - params.stop_listening_incoming_connection_error); - break; - case location::nearby::errorcode::proto::START_DISCOVERING: - error_code->set_start_discovering_error(params.start_discovering_error); - break; - case location::nearby::errorcode::proto::STOP_DISCOVERING: - error_code->set_stop_discovering_error(params.stop_discovering_error); - break; - case location::nearby::errorcode::proto::CONNECT: - error_code->set_connect_error(params.connect_error); - break; - case location::nearby::errorcode::proto::DISCONNECT: - error_code->set_disconnect_error(params.disconnect_error); - break; - case location::nearby::errorcode::proto::UNKNOWN_EVENT: - default: - error_code->set_common_error(params.common_error); - break; - } - } - - ConnectionsLog connections_log; - connections_log.set_event_type(ERROR_CODE); - connections_log.set_version(kVersion); - connections_log.set_allocated_error_code(error_code.release()); - - VLOG(1) << "AnalyticsRecorder LogErrorCode connections_log=" - << connections_log.DebugString(); // NOLINT - - event_logger_->Log(connections_log); -} - -void AnalyticsRecorder::LogStartSession() { - MutexLock lock(&mutex_); - if (start_client_session_was_logged_) { - LOG(WARNING) << "AnalyticsRecorder CanRecordAnalytics Unexpected call " - << kOnStartClientSession - << " after start client session has already been logged."; - return; - } - - session_was_logged_ = false; - if (CanRecordAnalyticsLocked(kOnStartClientSession)) { - client_session_ = std::make_unique(); - started_client_session_time_ = SystemClock::ElapsedRealtime(); - start_client_session_was_logged_ = true; - LogEvent(START_CLIENT_SESSION); - } -} - -void AnalyticsRecorder::LogSession() { - MutexLock lock(&mutex_); - if (!CanRecordAnalyticsLocked("LogSession")) { - return; - } - FinishStrategySessionLocked(); - client_session_->set_duration_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_client_session_time_)); - LogClientSessionLocked(); - LogEvent(STOP_CLIENT_SESSION); - start_client_session_was_logged_ = false; - session_was_logged_ = true; -} std::unique_ptr AnalyticsRecorder::BuildAdvertisingMetadataParams( bool is_extended_advertisement_supported, int connected_ap_frequency, bool is_nfc_available, - const std::vector& + const std::vector& operation_result_with_mediums) { auto params = std::make_unique(); params->is_extended_advertisement_supported = is_extended_advertisement_supported; params->connected_ap_frequency = connected_ap_frequency; params->is_nfc_available = is_nfc_available; - params->operation_result_with_mediums = - std::move(operation_result_with_mediums); + params->operation_result_with_mediums = operation_result_with_mediums; return params; } @@ -936,15 +50,14 @@ std::unique_ptr AnalyticsRecorder::BuildDiscoveryMetadataParams( bool is_extended_advertisement_supported, int connected_ap_frequency, bool is_nfc_available, - const std::vector& + const std::vector& operation_result_with_mediums) { auto params = std::make_unique(); params->is_extended_advertisement_supported = is_extended_advertisement_supported; params->connected_ap_frequency = connected_ap_frequency; params->is_nfc_available = is_nfc_available; - params->operation_result_with_mediums = - std::move(operation_result_with_mediums); + params->operation_result_with_mediums = operation_result_with_mediums; return params; } @@ -1000,694 +113,4 @@ OperationResultCode AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( } } -bool AnalyticsRecorder::CanRecordAnalyticsLocked( - absl::string_view method_name) { - VLOG(1) << "AnalyticsRecorder LogEvent " << method_name << " is calling."; - if (event_logger_ == nullptr) { - return false; - } - - if (session_was_logged_) { - VLOG(1) << "AnalyticsRecorder CanRecordAnalytics Unexpected call " - << method_name << " after session has already been logged."; - return false; - } - - return true; -} - -// TODO: b/391339677 - Investigate why we need to reset the resources. And -// verify in b/238375695 to see if we still meet the issue after removing the -// Reset function. -void AnalyticsRecorder::LogClientSessionLocked() { - ConnectionsLog connections_log; - connections_log.set_event_type(CLIENT_SESSION); - connections_log.set_allocated_client_session(client_session_.release()); - connections_log.set_version(kVersion); - - VLOG(1) << "AnalyticsRecorder LogClientSession connections_log=" - << connections_log.DebugString(); // NOLINT - - event_logger_->Log(connections_log); - client_session_ = nullptr; -} - -void AnalyticsRecorder::LogEvent(EventType event_type) { - ConnectionsLog connections_log; - connections_log.set_event_type(event_type); - connections_log.set_version(kVersion); - - VLOG(1) << "AnalyticsRecorder LogEvent connections_log=" - << connections_log.DebugString(); // NOLINT - - event_logger_->Log(connections_log); -} - -void AnalyticsRecorder::UpdateStrategySessionLocked( - connections::Strategy strategy, SessionRole role) { - // If we're not switching strategies, just update the current StrategySession - // with the new role. - if (strategy == current_strategy_ && current_strategy_session_ != nullptr) { - if (absl::c_linear_search(current_strategy_session_->role(), role)) { - // We've already acted as this role before, so make sure we've finished - // recording the previous round. - switch (role) { - case ADVERTISER: - FinishAdvertisingPhaseLocked(); - break; - case DISCOVERER: - FinishDiscoveryPhaseLocked(); - break; - default: - break; - } - } else { - current_strategy_session_->add_role(role); - } - } else { - // Otherwise, we're starting a new Strategy. - current_strategy_ = strategy; - FinishStrategySessionLocked(); - LogEvent(START_STRATEGY_SESSION); - current_strategy_session_ = - std::make_unique(); - started_strategy_session_time_ = SystemClock::ElapsedRealtime(); - current_strategy_session_->set_strategy( - StrategyToConnectionStrategy(strategy)); - current_strategy_session_->add_role(role); - } -} - -void AnalyticsRecorder::RecordAdvertisingPhaseDurationAndReasonLocked( - bool on_stop) const { - if (current_advertising_phase_ == nullptr) { - LOG(INFO) << "Unable to record advertising phase duration due to " - "null current_advertising_phase_"; - return; - } - if (!current_advertising_phase_->has_duration_millis()) { - current_advertising_phase_->set_duration_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_advertising_phase_time_)); - } - if (!current_advertising_phase_->has_stop_reason()) { - current_advertising_phase_->set_stop_reason( - on_stop ? StopAdvertisingReason::CLIENT_STOP_ADVERTISING - : StopAdvertisingReason::FINISH_SESSION_STOP_ADVERTISING); - } -} - -void AnalyticsRecorder::FinishAdvertisingPhaseLocked() { - if (current_advertising_phase_ != nullptr) { - for (const auto& item : incoming_connection_requests_) { - // ConnectionRequests still pending have been ignored by the local or - // remote (or both) endpoints. - const std::unique_ptr& - connection_request = item.second; - MarkConnectionRequestIgnoredLocked(connection_request.get()); - UpdateAdvertiserConnectionRequestLocked(connection_request.get()); - } - RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); - if (current_strategy_session_ != nullptr) { - *current_strategy_session_->add_advertising_phase() = - *std::move(current_advertising_phase_); - } else { - LOG(INFO) << "Unable to record advertising phase due to null " - "current_strategy_session_"; - } - } - incoming_connection_requests_.clear(); -} - -void AnalyticsRecorder::RecordDiscoveryPhaseDurationAndReasonLocked( - bool on_stop) const { - if (current_discovery_phase_ == nullptr) { - LOG(INFO) << "Unable to record discovery phase duration due to " - "null current_discovery_phase_"; - return; - } - if (!current_discovery_phase_->has_duration_millis()) { - current_discovery_phase_->set_duration_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_discovery_phase_time_)); - } - // If the stop reason haven't been set yet, then set it. - if (!current_discovery_phase_->has_stop_reason()) { - current_discovery_phase_->set_stop_reason( - on_stop ? StopDiscoveringReason::CLIENT_STOP_DISCOVERING - : StopDiscoveringReason::FINISH_SESSION_STOP_DISCOVERING); - } -} - -void AnalyticsRecorder::FinishDiscoveryPhaseLocked() { - if (current_discovery_phase_ != nullptr) { - for (const auto& item : outgoing_connection_requests_) { - // ConnectionRequests still pending have been ignored by the local or - // remote (or both) endpoints. - const std::unique_ptr& - connection_request = item.second; - MarkConnectionRequestIgnoredLocked(connection_request.get()); - UpdateDiscovererConnectionRequestLocked(connection_request.get()); - } - RecordDiscoveryPhaseDurationAndReasonLocked(/* on_stop=*/false); - if (current_strategy_session_ != nullptr) { - *current_strategy_session_->add_discovery_phase() = - *std::move(current_discovery_phase_); - } else { - LOG(INFO) << "Unable to record discovery phase due to null " - "current_strategy_session_"; - } - } - outgoing_connection_requests_.clear(); -} - -bool AnalyticsRecorder::UpdateAdvertiserConnectionRequestLocked( - ConnectionsLog::ConnectionRequest* request) { - if (current_advertising_phase_ == nullptr) { - LOG(INFO) << "Unable to record advertiser connection request due to null " - "current_advertising_phase_"; - return false; - } - if (BothEndpointsRespondedLocked(request)) { - request->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - request->duration_millis()); - *current_advertising_phase_->add_received_connection_request() = *request; - return true; - } - return false; -} - -bool AnalyticsRecorder::UpdateDiscovererConnectionRequestLocked( - ConnectionsLog::ConnectionRequest* request) { - if (current_discovery_phase_ == nullptr) { - LOG(INFO) << "Unable to record discoverer connection request due " - "to null current_discovery_phase_."; - return false; - } - if (BothEndpointsRespondedLocked(request) || - request->local_response() == NOT_SENT) { - request->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - request->duration_millis()); - *current_discovery_phase_->add_sent_connection_request() = *request; - return true; - } - return false; -} - -bool AnalyticsRecorder::BothEndpointsRespondedLocked( - ConnectionsLog::ConnectionRequest* request) { - return request->has_local_response() && request->has_remote_response(); -} - -void AnalyticsRecorder::LocalEndpointRespondedLocked( - const std::string& remote_endpoint_id, ConnectionRequestResponse response) { - auto out = outgoing_connection_requests_.find(remote_endpoint_id); - if (out != outgoing_connection_requests_.end()) { - ConnectionsLog::ConnectionRequest* connection_request = out->second.get(); - connection_request->set_local_response(response); - if (UpdateDiscovererConnectionRequestLocked(connection_request)) { - outgoing_connection_requests_.erase(out); - } - } - auto in = incoming_connection_requests_.find(remote_endpoint_id); - if (in != incoming_connection_requests_.end()) { - ConnectionsLog::ConnectionRequest* connection_request = in->second.get(); - connection_request->set_local_response(response); - if (UpdateAdvertiserConnectionRequestLocked(connection_request)) { - incoming_connection_requests_.erase(in); - } - } -} - -void AnalyticsRecorder::RemoteEndpointRespondedLocked( - const std::string& remote_endpoint_id, ConnectionRequestResponse response) { - auto out = outgoing_connection_requests_.find(remote_endpoint_id); - if (out != outgoing_connection_requests_.end()) { - ConnectionsLog::ConnectionRequest* connection_request = out->second.get(); - connection_request->set_remote_response(response); - if (UpdateDiscovererConnectionRequestLocked(connection_request)) { - outgoing_connection_requests_.erase(out); - } - } - auto in = incoming_connection_requests_.find(remote_endpoint_id); - if (in != incoming_connection_requests_.end()) { - ConnectionsLog::ConnectionRequest* connection_request = in->second.get(); - connection_request->set_remote_response(response); - if (UpdateAdvertiserConnectionRequestLocked(connection_request)) { - incoming_connection_requests_.erase(in); - } - } -} - -void AnalyticsRecorder::MarkConnectionRequestIgnoredLocked( - ConnectionsLog::ConnectionRequest* request) { - if (!request->has_local_response()) { - request->set_local_response(IGNORED); - } - if (!request->has_remote_response()) { - request->set_remote_response(IGNORED); - } -} - -bool AnalyticsRecorder::ConnectionAttemptResultCodeExistedLocked( - Medium medium, ConnectionAttemptDirection direction, - const std::string& connection_token, ConnectionAttemptType type, - OperationResultCode operation_result_code) { - if (current_strategy_session_ == nullptr || - current_strategy_session_->connection_attempt_size() == 0) { - return false; - } - for (auto& connection_attempt : - current_strategy_session_->connection_attempt()) { - if (connection_attempt.medium() == medium && - connection_attempt.direction() == direction && - connection_attempt.connection_token() == connection_token && - connection_attempt.type() == type && - connection_attempt.operation_result().result_code() == - operation_result_code) { - return true; - } - } - - return false; -} - -// If bandwidth upgrade always failed on the same fromMedium, toMedium, result, -// stage and result code, we'll drop the duplicate logs for preventing the waste -// of log storage space -bool AnalyticsRecorder::EraseIfBandwidthUpgradeRecordExistedLocked( - const std::string& endpoint_id, BandwidthUpgradeResult result, - BandwidthUpgradeErrorStage error_stage, - OperationResultCode operation_result_code) { - if (current_strategy_session_ == nullptr) { - return false; - } - auto it = bandwidth_upgrade_attempts_.find(endpoint_id); - if (it != bandwidth_upgrade_attempts_.end()) { - ConnectionsLog::BandwidthUpgradeAttempt* attempt = it->second.get(); - for (auto& existing_attempt : - current_strategy_session_->upgrade_attempt()) { - if (attempt->from_medium() == existing_attempt.from_medium() && - attempt->to_medium() == existing_attempt.to_medium() && - result == existing_attempt.upgrade_result() && - error_stage == existing_attempt.error_stage() && - operation_result_code == - existing_attempt.operation_result().result_code()) { - bandwidth_upgrade_attempts_.erase(it); - return true; - } - } - } - return false; -} - -void AnalyticsRecorder::FinishUpgradeAttemptLocked( - const std::string& endpoint_id, BandwidthUpgradeResult result, - BandwidthUpgradeErrorStage error_stage, - OperationResultCode operation_result_code, bool erase_item) { - if (current_strategy_session_ == nullptr) { - LOG(INFO) << "Unable to record upgrade attempt due to null " - "current_strategy_session_"; - return; - } - // Add the BandwidthUpgradeAttempt in the current StrategySession. - auto it = bandwidth_upgrade_attempts_.find(endpoint_id); - if (it != bandwidth_upgrade_attempts_.end()) { - ConnectionsLog::BandwidthUpgradeAttempt* attempt = it->second.get(); - attempt->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - attempt->duration_millis()); - attempt->set_error_stage(error_stage); - attempt->set_upgrade_result(result); - - auto operation_result_proto = - std::make_unique(); - operation_result_proto->set_result_code(operation_result_code); - operation_result_proto->set_result_category( - ConvertToOperationResultCategory(operation_result_code)); - attempt->set_allocated_operation_result(operation_result_proto.release()); - *current_strategy_session_->add_upgrade_attempt() = *attempt; - if (erase_item) { - bandwidth_upgrade_attempts_.erase(it); - } - } -} - -void AnalyticsRecorder::FinishStrategySessionLocked() { - if (current_strategy_session_ != nullptr) { - FinishAdvertisingPhaseLocked(); - FinishDiscoveryPhaseLocked(); - - // Finish any unfinished LogicalConnections. - for (const auto& item : active_connections_) { - const std::unique_ptr& logical_connection = - item.second; - logical_connection->CloseAllPhysicalConnections(); - absl::c_copy( - logical_connection->GetEstablisedConnections(), - RepeatedFieldBackInserter( - current_strategy_session_->mutable_established_connection())); - } - active_connections_.clear(); - - // Finish any pending upgrade attempts. - for (const auto& item : bandwidth_upgrade_attempts_) { - FinishUpgradeAttemptLocked( - item.first, UNFINISHED_ERROR, UPGRADE_UNFINISHED, - OperationResultCode::DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS, - /*erase_item=*/false); - } - bandwidth_upgrade_attempts_.clear(); - - // Add the StrategySession in ClientSession - if (current_strategy_session_ != nullptr) { - current_strategy_session_->set_duration_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_strategy_session_time_)); - *client_session_->add_strategy_session() = - *std::move(current_strategy_session_); - } - - current_strategy_session_ = nullptr; - current_strategy_ = connections::Strategy::kNone; - LogEvent(STOP_STRATEGY_SESSION); - } -} - -ConnectionsStrategy AnalyticsRecorder::StrategyToConnectionStrategy( - connections::Strategy strategy) { - if (strategy == connections::Strategy::kP2pCluster) { - return P2P_CLUSTER; - } - if (strategy == connections::Strategy::kP2pStar) { - return P2P_STAR; - } - if (strategy == connections::Strategy::kP2pPointToPoint) { - return P2P_POINT_TO_POINT; - } - return UNKNOWN_STRATEGY; -} - -PayloadType AnalyticsRecorder::PayloadTypeToProtoPayloadType( - connections::PayloadType type) { - switch (type) { - case connections::PayloadType::kBytes: - return BYTES; - case connections::PayloadType::kFile: - return FILE; - case connections::PayloadType::kStream: - return STREAM; - default: - return UNKNOWN_PAYLOAD_TYPE; - } -} - -void AnalyticsRecorder::PendingPayload::AddChunk( - std::int64_t chunk_size_bytes) { - num_bytes_transferred_ += chunk_size_bytes; - num_chunks_++; -} - -ConnectionsLog::Payload AnalyticsRecorder::PendingPayload::GetProtoPayload( - PayloadStatus status) { - ConnectionsLog::Payload payload; - payload.set_duration_millis( - absl::ToInt64Milliseconds(SystemClock::ElapsedRealtime() - start_time_)); - payload.set_type(type_); - payload.set_total_size_bytes(total_size_bytes_); - payload.set_num_bytes_transferred(num_bytes_transferred_); - payload.set_num_chunks(num_chunks_); - payload.set_status(status); - - auto operation_result_proto = - std::make_unique(); - operation_result_proto->set_result_code(operation_result_code_); - operation_result_proto->set_result_category( - ConvertToOperationResultCategory(operation_result_code_)); - payload.set_allocated_operation_result(operation_result_proto.release()); - - return payload; -} - -void AnalyticsRecorder::LogicalConnection::PhysicalConnectionEstablished( - Medium medium, const std::string& connection_token) { - if (current_medium_ != UNKNOWN_MEDIUM) { - LOG(WARNING) << "Unexpected call to PhysicalConnectionEstablished while " - "AnalyticsRecorder still has an active current medium."; - } - - auto established_connection = - std::make_unique(); - established_connection->set_medium(medium); - established_connection->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime())); - established_connection->set_connection_token(connection_token); - - auto operation_result_proto = - std::make_unique(); - operation_result_proto->set_result_code(OperationResultCode::DETAIL_SUCCESS); - operation_result_proto->set_result_category( - OperationResultCategory::CATEGORY_SUCCESS); - established_connection->set_allocated_operation_result( - operation_result_proto.release()); - physical_connections_.insert({medium, std::move(established_connection)}); - current_medium_ = medium; -} - -void AnalyticsRecorder::LogicalConnection::PhysicalConnectionClosed( - Medium medium, DisconnectionReason reason, SafeDisconnectionResult result) { - if (current_medium_ == UNKNOWN_MEDIUM) { - LOG(WARNING) << "Unexpected call to PhysicalConnectionClosed() for medium " - << Medium_Name(medium) - << " while AnalyticsRecorder has no active current medium"; - } else if (current_medium_ != medium) { - LOG(WARNING) << "Unexpected call to PhysicalConnectionClosed() for medium " - << Medium_Name(medium) - << "while AnalyticsRecorder has active medium " - << Medium_Name(current_medium_); - } - - auto it = physical_connections_.find(medium); - if (it == physical_connections_.end()) { - LOG(WARNING) - << "Unexpected call to physicalConnectionClosed() for medium " - << Medium_Name(medium) - << " with no corresponding EstablishedConnection that was previously" - " opened."; - return; - } - ConnectionsLog::EstablishedConnection* established_connection = - it->second.get(); - if (established_connection->has_disconnection_reason()) { - LOG(WARNING) << "Unexpected call to physicalConnectionClosed() for medium " - << Medium_Name(medium) - << " which already has disconnection reason " - << DisconnectionReason_Name( - established_connection->disconnection_reason()); - return; - } - FinishPhysicalConnection(established_connection, reason, result); - - if (medium == current_medium_) { - // If the EstablishedConnection we just closed was the one that we have - // marked as current, unset currentMedium. - current_medium_ = UNKNOWN_MEDIUM; - } -} - -void AnalyticsRecorder::LogicalConnection::CloseAllPhysicalConnections() { - for (const auto& physical_connection : physical_connections_) { - ConnectionsLog::EstablishedConnection* established_connection = - physical_connection.second.get(); - if (!established_connection->has_disconnection_reason()) { - FinishPhysicalConnection( - established_connection, UNFINISHED, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); - } - } - current_medium_ = UNKNOWN_MEDIUM; -} - -std::vector -AnalyticsRecorder::LogicalConnection::GetEstablisedConnections() { - std::vector established_connections; - if (current_medium_ != UNKNOWN_MEDIUM) { - LOG(WARNING) - << "AnalyticsRecorder expected no more active physical connections " - "before logging this endpoint connection."; - return established_connections; - } - std::transform(physical_connections_.begin(), physical_connections_.end(), - std::back_inserter(established_connections), - [](auto& kv) { return *kv.second; }); - physical_connections_.clear(); - - for (auto& established_connection : established_connections) { - if (absl::Milliseconds(established_connection.duration_millis()) >= - kConnectionTokenMaxLife) { - LOG(INFO) << "connection token exceed TTL, drop token."; - established_connection.set_connection_token(""); - } - } - - return established_connections; -} - -void AnalyticsRecorder::LogicalConnection::IncomingPayloadStarted( - std::int64_t payload_id, PayloadType type, std::int64_t total_size_bytes) { - incoming_payloads_.insert( - {payload_id, std::make_unique(type, total_size_bytes)}); -} - -void AnalyticsRecorder::LogicalConnection::ChunkReceived( - std::int64_t payload_id, std::int64_t size_bytes) { - auto it = incoming_payloads_.find(payload_id); - if (it == incoming_payloads_.end()) { - return; - } - PendingPayload* pending_payload = it->second.get(); - pending_payload->AddChunk(size_bytes); -} - -void AnalyticsRecorder::LogicalConnection::IncomingPayloadDone( - std::int64_t payload_id, PayloadStatus status, - OperationResultCode operation_result_code) { - if (current_medium_ == UNKNOWN_MEDIUM) { - LOG(WARNING) << "Unexpected call to incomingPayloadDone() while " - "AnalyticsRecorder has no active current medium."; - return; - } - auto it = physical_connections_.find(current_medium_); - if (it != physical_connections_.end()) { - const std::unique_ptr& - established_connection = it->second; - auto it = incoming_payloads_.find(payload_id); - if (it != incoming_payloads_.end()) { - it->second->SetOperationResultCode(operation_result_code); - *established_connection->add_received_payload() = - it->second->GetProtoPayload(status); - incoming_payloads_.erase(it); - } - } -} - -void AnalyticsRecorder::LogicalConnection::OutgoingPayloadStarted( - std::int64_t payload_id, PayloadType type, std::int64_t total_size_bytes) { - outgoing_payloads_.insert( - {payload_id, std::make_unique(type, total_size_bytes)}); -} - -void AnalyticsRecorder::LogicalConnection::ChunkSent(std::int64_t payload_id, - std::int64_t size_bytes) { - auto it = outgoing_payloads_.find(payload_id); - if (it == outgoing_payloads_.end()) { - return; - } - PendingPayload* payload = it->second.get(); - payload->AddChunk(size_bytes); -} - -void AnalyticsRecorder::LogicalConnection::OutgoingPayloadDone( - std::int64_t payload_id, PayloadStatus status, - OperationResultCode operation_result_code) { - if (current_medium_ == UNKNOWN_MEDIUM) { - LOG(WARNING) << "Unexpected call to outgoingPayloadDone() while " - "AnalyticsRecorder has no active current medium."; - return; - } - auto it = physical_connections_.find(current_medium_); - if (it != physical_connections_.end()) { - const std::unique_ptr& - established_connection = it->second; - auto it = outgoing_payloads_.find(payload_id); - if (it != outgoing_payloads_.end()) { - it->second->SetOperationResultCode(operation_result_code); - *established_connection->add_sent_payload() = - it->second->GetProtoPayload(status); - outgoing_payloads_.erase(it); - } - } -} - -void AnalyticsRecorder::LogicalConnection::FinishPhysicalConnection( - ConnectionsLog::EstablishedConnection* established_connection, - DisconnectionReason reason, SafeDisconnectionResult result) { - established_connection->set_disconnection_reason(reason); - established_connection->set_safe_disconnection_result(result); - established_connection->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - established_connection->duration_millis()); - - // Add any not-yet-finished payloads to this EstablishedConnection. - std::vector in_payloads = - ResolvePendingPayloads(incoming_payloads_, reason); - absl::c_move(in_payloads, - RepeatedFieldBackInserter( - established_connection->mutable_received_payload())); - std::vector out_payloads = - ResolvePendingPayloads(outgoing_payloads_, reason); - absl::c_move(out_payloads, - RepeatedFieldBackInserter( - established_connection->mutable_sent_payload())); -} - -std::vector -AnalyticsRecorder::LogicalConnection::ResolvePendingPayloads( - absl::btree_map>& - pending_payloads, - DisconnectionReason reason) { - std::vector completed_payloads; - absl::btree_map> - upgraded_payloads; - PayloadStatus status = - reason == UPGRADED ? MOVED_TO_NEW_MEDIUM : CONNECTION_CLOSED; - - OperationResultCode operation_result_code = - GetPendingPayloadResultCodeFromReason(reason); - for (const auto& item : pending_payloads) { - const std::unique_ptr& pending_payload = item.second; - pending_payload->SetOperationResultCode(operation_result_code); - ConnectionsLog::Payload proto_payload = - pending_payload->GetProtoPayload(status); - completed_payloads.push_back(proto_payload); - if (reason == UPGRADED) { - upgraded_payloads.insert( - {item.first, - std::make_unique(pending_payload->type(), - pending_payload->total_size_bytes(), - operation_result_code)}); - } - } - pending_payloads.clear(); - - if (reason == UPGRADED) { - // Re-populate the map with a new PendingPayload for each pending payload, - // since we expect them to be completed on the next EstablishedConnection. - pending_payloads = std::move(upgraded_payloads); - } - // Return the list of completed payloads to be added to the current - // EstablishedConnection. - return completed_payloads; -} - -OperationResultCode -AnalyticsRecorder::LogicalConnection::GetPendingPayloadResultCodeFromReason( - DisconnectionReason reason) { - switch (reason) { - case UPGRADED: - return OperationResultCode::MISCELLEANEOUS_MOVE_TO_NEW_MEDIUM; - case DisconnectionReason::LOCAL_DISCONNECTION: - return OperationResultCode::CLIENT_CANCELLATION_LOCAL_DISCONNECT; - case DisconnectionReason::REMOTE_DISCONNECTION: - return OperationResultCode::CLIENT_CANCELLATION_REMOTE_DISCONNECT; - default: - return OperationResultCode::NEARBY_GENERIC_CONNECTION_CLOSED; - } -} - -OperationResultCategory AnalyticsRecorder::GetOperationResultCategory( - location::nearby::proto::connections::OperationResultCode result_code) { - return ConvertToOperationResultCategory(result_code); -} - -} // namespace analytics -} // namespace nearby +} // namespace nearby::analytics diff --git a/connections/implementation/analytics/analytics_recorder.h b/connections/implementation/analytics/analytics_recorder.h index b24232b3..601d12bc 100644 --- a/connections/implementation/analytics/analytics_recorder.h +++ b/connections/implementation/analytics/analytics_recorder.h @@ -18,118 +18,98 @@ #include #include #include -#include #include -#include "absl/base/thread_annotations.h" -#include "absl/container/btree_map.h" -#include "absl/strings/string_view.h" #include "absl/time/time.h" #include "connections/implementation/analytics/advertising_metadata_params.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" #include "connections/implementation/analytics/discovery_metadata_params.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "connections/payload_type.h" #include "connections/strategy.h" -#include "internal/analytics/event_logger.h" #include "internal/platform/error_code_params.h" -#include "internal/platform/implementation/system_clock.h" -#include "internal/platform/mutex.h" -#include "internal/proto/analytics/connections_log.pb.h" #include "proto/connections_enums.pb.h" -namespace nearby { -namespace analytics { +namespace nearby::analytics { + +enum class SafeDisconnectionResult { + kUnknown = 0, + kSafeDisconnection = 1, + kUnsafeDisconnection = 2, +}; class AnalyticsRecorder { public: - explicit AnalyticsRecorder(::nearby::analytics::EventLogger* event_logger); - virtual ~AnalyticsRecorder(); + AnalyticsRecorder() = default; + virtual ~AnalyticsRecorder() = default; // Advertising phase - void OnStartAdvertising( + virtual void OnStartAdvertising( connections::Strategy strategy, const std::vector& mediums, - AdvertisingMetadataParams* advertising_metadata_params) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnStopAdvertising() ABSL_LOCKS_EXCLUDED(mutex_); + AdvertisingMetadataParams* advertising_metadata_params) = 0; + virtual void OnStopAdvertising() = 0; - // In case the client calls the {@link BasePcp#updateAdvertisingOptions()} - // multiple times, adds one index value to group the mediums results within - // the same UpdateAdvertisingOptions call, this API is to return the largest - // index value in current_advertising_phase. - int GetNextAdvertisingUpdateIndex() ABSL_LOCKS_EXCLUDED(mutex_); + virtual int GetNextAdvertisingUpdateIndex() = 0; // Connection listening - void OnStartedIncomingConnectionListening(connections::Strategy strategy) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnStoppedIncomingConnectionListening() ABSL_LOCKS_EXCLUDED(mutex_); + virtual void OnStartedIncomingConnectionListening( + connections::Strategy strategy) = 0; + virtual void OnStoppedIncomingConnectionListening() = 0; // Discovery phase - void OnStartDiscovery( + virtual void OnStartDiscovery( connections::Strategy strategy, const std::vector& mediums, - DiscoveryMetadataParams* discovery_metadata_params) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnStopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_); + DiscoveryMetadataParams* discovery_metadata_params) = 0; + virtual void OnStopDiscovery() = 0; - // In case the client calls the {@link BasePcp#updateDiscoveryOptions()} - // multiple times, adds one index value to group the medium results within the - // same UpdateDiscoveryOptions call, this - // API is to return the latest index value in current_discovery_phase. - int GetNextDiscoveryUpdateIndex() ABSL_LOCKS_EXCLUDED(mutex_); - void OnEndpointFound(location::nearby::proto::connections::Medium medium) - ABSL_LOCKS_EXCLUDED(mutex_); + virtual int GetNextDiscoveryUpdateIndex() = 0; + virtual void OnEndpointFound( + location::nearby::proto::connections::Medium medium) = 0; // Connection request - void OnRequestConnection(const connections::Strategy& strategy, - const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); + virtual void OnRequestConnection(const connections::Strategy& strategy, + const std::string& endpoint_id) = 0; - void OnConnectionRequestReceived(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnConnectionRequestSent(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnRemoteEndpointAccepted(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnLocalEndpointAccepted(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnRemoteEndpointRejected(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnLocalEndpointRejected(const std::string& remote_endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); + virtual void OnConnectionRequestReceived( + const std::string& remote_endpoint_id) = 0; + virtual void OnConnectionRequestSent( + const std::string& remote_endpoint_id) = 0; + virtual void OnRemoteEndpointAccepted( + const std::string& remote_endpoint_id) = 0; + virtual void OnLocalEndpointAccepted( + const std::string& remote_endpoint_id) = 0; + virtual void OnRemoteEndpointRejected( + const std::string& remote_endpoint_id) = 0; + virtual void OnLocalEndpointRejected( + const std::string& remote_endpoint_id) = 0; // Connection attempt - // Records an attempt with meta data at establishing an incoming physical - // connection. - void OnIncomingConnectionAttempt( + virtual void OnIncomingConnectionAttempt( location::nearby::proto::connections::ConnectionAttemptType type, location::nearby::proto::connections::Medium medium, location::nearby::proto::connections::ConnectionAttemptResult result, absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) - ABSL_LOCKS_EXCLUDED(mutex_); - // Records an attempt with meta data at establishing an outgoing physical - // connection. - void OnOutgoingConnectionAttempt( + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) = 0; + virtual void OnOutgoingConnectionAttempt( const std::string& remote_endpoint_id, location::nearby::proto::connections::ConnectionAttemptType type, location::nearby::proto::connections::Medium medium, location::nearby::proto::connections::ConnectionAttemptResult result, absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) - ABSL_LOCKS_EXCLUDED(mutex_); + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) = 0; + static std::unique_ptr BuildAdvertisingMetadataParams( bool is_extended_advertisement_supported = false, int connected_ap_frequency = 0, bool is_nfc_available = false, - const std::vector& + const std::vector& operation_result_with_mediums = {}); static std::unique_ptr BuildDiscoveryMetadataParams( bool is_extended_advertisement_supported = false, int connected_ap_frequency = 0, bool is_nfc_available = false, - const std::vector& + const std::vector& operation_result_with_mediums = {}); static std::unique_ptr @@ -147,363 +127,78 @@ class AnalyticsRecorder { GetChannelIoErrorResultCodeFromMedium( location::nearby::proto::connections::Medium medium); - // Connection establishedSafeDisconnectionResult - void OnConnectionEstablished( + // Connection established + virtual void OnConnectionEstablished( const std::string& endpoint_id, location::nearby::proto::connections::Medium medium, - const std::string& connection_token) ABSL_LOCKS_EXCLUDED(mutex_); - void OnConnectionClosed( + const std::string& connection_token) = 0; + virtual void OnConnectionClosed( const std::string& endpoint_id, location::nearby::proto::connections::Medium medium, location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result) - ABSL_LOCKS_EXCLUDED(mutex_); + SafeDisconnectionResult result) = 0; // Payload - void OnIncomingPayloadStarted(const std::string& endpoint_id, - std::int64_t payload_id, - connections::PayloadType type, - std::int64_t total_size_bytes) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnPayloadChunkReceived(const std::string& endpoint_id, - std::int64_t payload_id, - std::int64_t chunk_size_bytes) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnIncomingPayloadDone( + virtual void OnIncomingPayloadStarted(const std::string& endpoint_id, + std::int64_t payload_id, + connections::PayloadType type, + std::int64_t total_size_bytes) = 0; + virtual void OnPayloadChunkReceived(const std::string& endpoint_id, + std::int64_t payload_id, + std::int64_t chunk_size_bytes) = 0; + virtual void OnIncomingPayloadDone( const std::string& endpoint_id, std::int64_t payload_id, location::nearby::proto::connections::PayloadStatus status, location::nearby::proto::connections::OperationResultCode - operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_); - void OnOutgoingPayloadStarted(const std::vector& endpoint_ids, - std::int64_t payload_id, - connections::PayloadType type, - std::int64_t total_size_bytes) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnPayloadChunkSent(const std::string& endpoint_id, - std::int64_t payload_id, - std::int64_t chunk_size_bytes) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnOutgoingPayloadDone( + operation_result_code) = 0; + virtual void OnOutgoingPayloadStarted( + const std::vector& endpoint_ids, std::int64_t payload_id, + connections::PayloadType type, std::int64_t total_size_bytes) = 0; + virtual void OnPayloadChunkSent(const std::string& endpoint_id, + std::int64_t payload_id, + std::int64_t chunk_size_bytes) = 0; + virtual void OnOutgoingPayloadDone( const std::string& endpoint_id, std::int64_t payload_id, location::nearby::proto::connections::PayloadStatus status, location::nearby::proto::connections::OperationResultCode - operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_); + operation_result_code) = 0; // BandwidthUpgrade - void OnBandwidthUpgradeStarted( + virtual void OnBandwidthUpgradeStarted( const std::string& endpoint_id, location::nearby::proto::connections::Medium from_medium, location::nearby::proto::connections::Medium to_medium, location::nearby::proto::connections::ConnectionAttemptDirection direction, - const std::string& connection_token) ABSL_LOCKS_EXCLUDED(mutex_); - void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id, - int num_interfaces, - int num_ipv6_only_interfaces) - ABSL_LOCKS_EXCLUDED(mutex_); - void OnBandwidthUpgradeError( + const std::string& connection_token) = 0; + virtual void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id, + int num_interfaces, + int num_ipv6_only_interfaces) = 0; + virtual void OnBandwidthUpgradeError( const std::string& endpoint_id, location::nearby::proto::connections::BandwidthUpgradeResult result, location::nearby::proto::connections::BandwidthUpgradeErrorStage error_stage, location::nearby::proto::connections::OperationResultCode - operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_); - void OnBandwidthUpgradeSuccess(const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); + operation_result_code) = 0; + virtual void OnBandwidthUpgradeSuccess(const std::string& endpoint_id) = 0; // Error Code - void OnErrorCode(const ErrorCodeParams& params); + virtual void OnErrorCode(const ErrorCodeParams& params) = 0; - // Log the start client session event with start client session logging - // resources setup (e.g. client_session_, started_client_session_time_) - void LogStartSession() ABSL_LOCKS_EXCLUDED(mutex_); + virtual void LogStartSession() = 0; + virtual void LogSession() = 0; - // Invokes event_logger_.Log() at the end of life of client. Log action is - // called in a separate thread to allow synchronous potentially lengthy - // execution. - void LogSession() ABSL_LOCKS_EXCLUDED(mutex_); + virtual bool IsSessionLogged() = 0; - bool IsSessionLogged(); - - location::nearby::proto::connections::OperationResultCategory + virtual location::nearby::proto::connections::OperationResultCategory GetOperationResultCategory( - location::nearby::proto::connections::OperationResultCode result_code); - - // Waits until all logs are sent to the backend. - // For testing only. - void Sync(); - - private: - // Tracks the chunks and duration of a Payload on a particular medium. - class PendingPayload { - public: - PendingPayload(location::nearby::proto::connections::PayloadType type, - std::int64_t total_size_bytes) - : PendingPayload(type, total_size_bytes, - location::nearby::proto::connections:: - OperationResultCode::DETAIL_UNKNOWN) {} - PendingPayload(location::nearby::proto::connections::PayloadType type, - std::int64_t total_size_bytes, - location::nearby::proto::connections::OperationResultCode - operation_result_code) - : start_time_(SystemClock::ElapsedRealtime()), - type_(type), - total_size_bytes_(total_size_bytes), - num_bytes_transferred_(0), - num_chunks_(0), - operation_result_code_(operation_result_code) {} - ~PendingPayload() = default; - - void AddChunk(std::int64_t chunk_size_bytes); - - location::nearby::analytics::proto::ConnectionsLog::Payload GetProtoPayload( - location::nearby::proto::connections::PayloadStatus status); - - location::nearby::proto::connections::PayloadType type() const { - return type_; - } - - std::int64_t total_size_bytes() const { return total_size_bytes_; } - - void SetOperationResultCode( - location::nearby::proto::connections::OperationResultCode - operation_result_code) { - operation_result_code_ = operation_result_code; - } - - private: - absl::Time start_time_; - location::nearby::proto::connections::PayloadType type_; - std::int64_t total_size_bytes_; - std::int64_t num_bytes_transferred_; - int num_chunks_; - location::nearby::proto::connections::OperationResultCode - operation_result_code_ = location::nearby::proto::connections:: - OperationResultCode::DETAIL_UNKNOWN; - }; - - class LogicalConnection { - public: - LogicalConnection( - location::nearby::proto::connections::Medium initial_medium, - const std::string& connection_token) { - PhysicalConnectionEstablished(initial_medium, connection_token); - } - LogicalConnection(const LogicalConnection&) = delete; - LogicalConnection(LogicalConnection&& other) - : current_medium_(std::move(other.current_medium_)), - physical_connections_(std::move(other.physical_connections_)), - incoming_payloads_(std::move(other.incoming_payloads_)), - outgoing_payloads_(std::move(other.outgoing_payloads_)) {} - LogicalConnection& operator=(const LogicalConnection&) = delete; - LogicalConnection&& operator=(LogicalConnection&&) = delete; - ~LogicalConnection() = default; - - void PhysicalConnectionEstablished( - location::nearby::proto::connections::Medium medium, - const std::string& connection_token); - void PhysicalConnectionClosed( - location::nearby::proto::connections::Medium medium, - location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result); - void CloseAllPhysicalConnections(); - - void IncomingPayloadStarted( - std::int64_t payload_id, - location::nearby::proto::connections::PayloadType type, - std::int64_t total_size_bytes); - void ChunkReceived(std::int64_t payload_id, std::int64_t size_bytes); - void IncomingPayloadDone( - std::int64_t payload_id, - location::nearby::proto::connections::PayloadStatus status, - location::nearby::proto::connections::OperationResultCode - operation_result_code); - void OutgoingPayloadStarted( - std::int64_t payload_id, - location::nearby::proto::connections::PayloadType type, - std::int64_t total_size_bytes); - void ChunkSent(std::int64_t payload_id, std::int64_t size_bytes); - void OutgoingPayloadDone( - std::int64_t payload_id, - location::nearby::proto::connections::PayloadStatus status, - location::nearby::proto::connections::OperationResultCode - operation_result_code); - - std::vector - GetEstablisedConnections(); - - private: - void FinishPhysicalConnection( - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection* established_connection, - location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result); - std::vector - ResolvePendingPayloads( - absl::btree_map>& - pending_payloads, - location::nearby::proto::connections::DisconnectionReason reason); - location::nearby::proto::connections::OperationResultCode - GetPendingPayloadResultCodeFromReason( - location::nearby::proto::connections::DisconnectionReason reason); - - location::nearby::proto::connections::Medium current_medium_ = - location::nearby::proto::connections::UNKNOWN_MEDIUM; - absl::btree_map> - physical_connections_; - absl::btree_map> - incoming_payloads_; - absl::btree_map> - outgoing_payloads_; - }; - - bool CanRecordAnalyticsLocked(absl::string_view method_name) - ABSL_SHARED_LOCKS_REQUIRED(mutex_); - - // Callbacks the ConnectionsLog proto byte array data to the EventLogger with - // ClientSession sub-proto. - void LogClientSessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - // Callbacks the ConnectionsLog proto byte array data to the EventLogger. - void LogEvent(location::nearby::proto::connections::EventType event_type); - - void UpdateStrategySessionLocked( - connections::Strategy strategy, - location::nearby::proto::connections::SessionRole role) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void RecordAdvertisingPhaseDurationAndReasonLocked(bool on_stop) const - ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void FinishAdvertisingPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void RecordDiscoveryPhaseDurationAndReasonLocked(bool on_stop) const - ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void FinishDiscoveryPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - bool UpdateAdvertiserConnectionRequestLocked( - location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* - request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - bool UpdateDiscovererConnectionRequestLocked( - location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* - request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - bool BothEndpointsRespondedLocked( - location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* - request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void LocalEndpointRespondedLocked( - const std::string& remote_endpoint_id, - location::nearby::proto::connections::ConnectionRequestResponse response) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void RemoteEndpointRespondedLocked( - const std::string& remote_endpoint_id, - location::nearby::proto::connections::ConnectionRequestResponse response) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void MarkConnectionRequestIgnoredLocked( - location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* - request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void OnIncomingConnectionAttemptLocked( - location::nearby::proto::connections::ConnectionAttemptType type, - location::nearby::proto::connections::Medium medium, - location::nearby::proto::connections::ConnectionAttemptResult result, - absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) - ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void OnOutgoingConnectionAttemptLocked( - const std::string& remote_endpoint_id, - location::nearby::proto::connections::ConnectionAttemptType type, - location::nearby::proto::connections::Medium medium, - location::nearby::proto::connections::ConnectionAttemptResult result, - absl::Duration duration, const std::string& connection_token, - ConnectionAttemptMetadataParams* connection_attempt_metadata_params) - ABSL_SHARED_LOCKS_REQUIRED(mutex_); - bool ConnectionAttemptResultCodeExistedLocked( - location::nearby::proto::connections::Medium medium, - location::nearby::proto::connections::ConnectionAttemptDirection - direction, - const std::string& connection_token, - location::nearby::proto::connections::ConnectionAttemptType type, location::nearby::proto::connections::OperationResultCode - operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - bool EraseIfBandwidthUpgradeRecordExistedLocked( - const std::string& endpoint_id, - location::nearby::proto::connections::BandwidthUpgradeResult result, - location::nearby::proto::connections::BandwidthUpgradeErrorStage - error_stage, - location::nearby::proto::connections::OperationResultCode - operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void FinishUpgradeAttemptLocked( - const std::string& endpoint_id, - location::nearby::proto::connections::BandwidthUpgradeResult result, - location::nearby::proto::connections::BandwidthUpgradeErrorStage - error_stage, - location::nearby::proto::connections::OperationResultCode - operation_result_code, - bool erase_item = true) ABSL_SHARED_LOCKS_REQUIRED(mutex_); - void FinishStrategySessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + result_code) = 0; - int GetLatestUpdateIndexLocked( - const std::vector& list) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - location::nearby::proto::connections::ConnectionsStrategy - StrategyToConnectionStrategy(connections::Strategy strategy); - location::nearby::proto::connections::PayloadType - PayloadTypeToProtoPayloadType(connections::PayloadType type); - - // Not owned by AnalyticsRecorder. Pointer must refer to a valid object - // that outlives the one constructed. - ::nearby::analytics::EventLogger* event_logger_; - - // Protects all sub-protos reading and writing in ConnectionLog. - Mutex mutex_; - - // ClientSession - std::unique_ptr< - location::nearby::analytics::proto::ConnectionsLog::ClientSession> - client_session_; - absl::Time started_client_session_time_; - bool session_was_logged_ ABSL_GUARDED_BY(mutex_) = false; - bool start_client_session_was_logged_ ABSL_GUARDED_BY(mutex_) = false; - - // Current StrategySession - connections::Strategy current_strategy_ ABSL_GUARDED_BY(mutex_) = - connections::Strategy::kNone; - std::unique_ptr< - location::nearby::analytics::proto::ConnectionsLog::StrategySession> - current_strategy_session_ ABSL_GUARDED_BY(mutex_); - absl::Time started_strategy_session_time_ ABSL_GUARDED_BY(mutex_); - - // Current AdvertisingPhase - std::unique_ptr< - location::nearby::analytics::proto::ConnectionsLog::AdvertisingPhase> - current_advertising_phase_; - absl::Time started_advertising_phase_time_ = absl::InfinitePast(); - - // Current DiscoveryPhase - std::unique_ptr< - location::nearby::analytics::proto::ConnectionsLog::DiscoveryPhase> - current_discovery_phase_; - absl::Time started_discovery_phase_time_ = absl::InfinitePast(); - - absl::btree_map> - incoming_connection_requests_ ABSL_GUARDED_BY(mutex_); - absl::btree_map> - outgoing_connection_requests_ ABSL_GUARDED_BY(mutex_); - absl::btree_map> - active_connections_ ABSL_GUARDED_BY(mutex_); - absl::btree_map> - bandwidth_upgrade_attempts_ ABSL_GUARDED_BY(mutex_); + virtual void Sync() = 0; }; -} // namespace analytics -} // namespace nearby +} // namespace nearby::analytics #endif // ANALYTICS_ANALYTICS_RECORDER_H_ diff --git a/connections/implementation/analytics/analytics_recorder_impl.cc b/connections/implementation/analytics/analytics_recorder_impl.cc new file mode 100644 index 00000000..211cc2dd --- /dev/null +++ b/connections/implementation/analytics/analytics_recorder_impl.cc @@ -0,0 +1,1643 @@ +// Copyright 2022-2023 Google LLC +// +// 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 +// +// https://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. + +#include "connections/implementation/analytics/analytics_recorder_impl.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/container.h" +#include "absl/container/btree_map.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" +#include "connections/implementation/analytics/advertising_metadata_params.h" +#include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/connection_attempt_metadata_params.h" +#include "connections/implementation/analytics/discovery_metadata_params.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" +#include "connections/payload_type.h" +#include "connections/strategy.h" +#include "internal/analytics/event_logger.h" +#include "internal/platform/error_code_params.h" +#include "internal/platform/implementation/system_clock.h" +#include "internal/platform/logging.h" +#include "internal/platform/mutex_lock.h" +#include "internal/proto/analytics/connections_log.pb.h" +#include "proto/connections_enums.pb.h" +#include "google/protobuf/repeated_ptr_field.h" + +namespace nearby::analytics { + +namespace { +// const char kVersion_1_0_0[] = "v1.0.0"; +const char kVersion[] = "v1.5.0"; +constexpr absl::string_view kOnStartClientSession = "OnStartClientSession"; +const absl::Duration kConnectionTokenMaxLife = absl::Hours(24); + +using ::location::nearby::analytics::proto::ConnectionsLog; +using ::location::nearby::proto::connections::ACCEPTED; +using ::location::nearby::proto::connections::ADVERTISER; +using ::location::nearby::proto::connections::BandwidthUpgradeErrorStage; +using ::location::nearby::proto::connections::BandwidthUpgradeResult; +using ::location::nearby::proto::connections::BYTES; +using ::location::nearby::proto::connections::CLIENT_SESSION; +using ::location::nearby::proto::connections::CONNECTION_CLOSED; +using ::location::nearby::proto::connections::ConnectionAttemptDirection; +using ::location::nearby::proto::connections::ConnectionAttemptResult; +using ::location::nearby::proto::connections::ConnectionAttemptType; +using ::location::nearby::proto::connections::ConnectionRequestResponse; +using ::location::nearby::proto::connections::ConnectionsStrategy; +using ::location::nearby::proto::connections::DisconnectionReason; +using ::location::nearby::proto::connections::DISCOVERER; +using ::location::nearby::proto::connections::ERROR_CODE; +using ::location::nearby::proto::connections::EventType; +using ::location::nearby::proto::connections::FILE; +using ::location::nearby::proto::connections::IGNORED; +using ::location::nearby::proto::connections::INCOMING; +using ::location::nearby::proto::connections::INITIAL; +using ::location::nearby::proto::connections::Medium; +using ::location::nearby::proto::connections::MOVED_TO_NEW_MEDIUM; +using ::location::nearby::proto::connections::NOT_SENT; +using ::location::nearby::proto::connections::OperationResultCategory; +using ::location::nearby::proto::connections::OperationResultCode; +using ::location::nearby::proto::connections::OUTGOING; +using ::location::nearby::proto::connections::P2P_CLUSTER; +using ::location::nearby::proto::connections::P2P_POINT_TO_POINT; +using ::location::nearby::proto::connections::P2P_STAR; +using ::location::nearby::proto::connections::PayloadStatus; +using ::location::nearby::proto::connections::PayloadType; +using ::location::nearby::proto::connections::REJECTED; +using ::location::nearby::proto::connections::RESULT_SUCCESS; +using ::location::nearby::proto::connections::SessionRole; +using ::location::nearby::proto::connections::START_CLIENT_SESSION; +using ::location::nearby::proto::connections::START_STRATEGY_SESSION; +using ::location::nearby::proto::connections::STOP_CLIENT_SESSION; +using ::location::nearby::proto::connections::STOP_STRATEGY_SESSION; +using ::location::nearby::proto::connections::StopAdvertisingReason; +using ::location::nearby::proto::connections::StopDiscoveringReason; +using ::location::nearby::proto::connections::STREAM; +using ::location::nearby::proto::connections::UNFINISHED; +using ::location::nearby::proto::connections::UNFINISHED_ERROR; +using ::location::nearby::proto::connections::UNKNOWN_MEDIUM; +using ::location::nearby::proto::connections::UNKNOWN_PAYLOAD_TYPE; +using ::location::nearby::proto::connections::UNKNOWN_STRATEGY; +using ::location::nearby::proto::connections::UPGRADE_RESULT_SUCCESS; +using ::location::nearby::proto::connections::UPGRADE_SUCCESS; +using ::location::nearby::proto::connections::UPGRADE_UNFINISHED; +using ::location::nearby::proto::connections::UPGRADED; +using ::nearby::analytics::EventLogger; +using ProtoSafeDisconnectionResult = ::location::nearby::analytics::proto:: + ConnectionsLog::EstablishedConnection::SafeDisconnectionResult; + +OperationResultCategory ConvertToOperationResultCategory( + OperationResultCode result_code) { + if (result_code == OperationResultCode::DETAIL_SUCCESS) { + return OperationResultCategory::CATEGORY_SUCCESS; + } + // TODO(b/409865630): check later if we need to add back the dct error. + // Section of CATEGORY_DCT_ERROR, from 5000 to 5499 if (result_code + // >= OperationResultCode::DCT_ERROR_BLE_DISABLED) { + // return OperationResultCategory::CATEGORY_DCT_ERROR; + //} + + // Section of CATEGORY_NEARBY_ERROR, starting from 4500 to 4999 + if (result_code >= + OperationResultCode::NEARBY_BLE_ADVERTISEMENT_MAPPING_TO_MAC_ERROR) { + return OperationResultCategory::CATEGORY_NEARBY_ERROR; + } + // Section of CATEGORY_CONNECTIVITY_ERROR, starting from 3500 to 4499 + if (result_code >= + OperationResultCode::CONNECTIVITY_WIFI_AWARE_ATTACH_FAILURE) { + return OperationResultCategory::CATEGORY_CONNECTIVITY_ERROR; + } + // Section of CATEGORY_IO_ERROR, from 3000 to 3499 + if (result_code >= OperationResultCode::IO_FILE_OPENING_ERROR) { + return OperationResultCategory::CATEGORY_IO_ERROR; + } + // Section of CATEGORY_MISCELLANEOUS, from 2500 to 2999 + if (result_code >= + OperationResultCode::MISCELLEANEOUS_BLUETOOTH_MAC_ADDRESS_NULL) { + return OperationResultCategory::CATEGORY_MISCELLANEOUS; + } + // Section of CATEGORY_CLIENT_ERROR, from 2000 to 2499 + if (result_code >= + OperationResultCode:: + CLIENT_WIFI_DIRECT_ALREADY_HOSTING_DIRECT_GROUP_FOR_THIS_CLIENT) { + return OperationResultCategory::CATEGORY_CLIENT_ERROR; + } + // Section of CATEGORY_MEDIUM_UNAVAILABLE, from 1500 to 1999 + if (result_code >= OperationResultCode:: + MEDIUM_UNAVAILABLE_WIFI_AWARE_RESOURCE_NOT_AVAILABLE) { + return OperationResultCategory::CATEGORY_MEDIUM_UNAVAILABLE; + } + // Section of CATEGORY_DEVICE_STATE_ERROR, from 1000 to 1499 + if (result_code >= + OperationResultCode::DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS) { + return OperationResultCategory::CATEGORY_DEVICE_STATE_ERROR; + } + // Section of CATEGORY_CLIENT_CANCELLATION, from 500 to 999 + if (result_code >= + OperationResultCode::CLIENT_CANCELLATION_REMOTE_IN_CANCELED_STATE) { + return OperationResultCategory::CATEGORY_CLIENT_CANCELLATION; + } + // Clarify other non success cases as unknown + return OperationResultCategory::CATEGORY_UNKNOWN; +} + +ProtoSafeDisconnectionResult ConvertToProtoSafeDisconnectionResult( + SafeDisconnectionResult result) { + switch (result) { + case SafeDisconnectionResult::kSafeDisconnection: + return ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION; + case SafeDisconnectionResult::kUnsafeDisconnection: + return ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION; + default: + return ConnectionsLog::EstablishedConnection:: + UNKNOWN_SAFE_DISCONNECTION_RESULT; + } +} + +ConnectionsLog::OperationResultWithMedium +ConvertToProtoOperationResultWithMedium( + const nearby::analytics::OperationResultWithMedium& cpp_result) { + ConnectionsLog::OperationResultWithMedium proto_result; + proto_result.set_medium(cpp_result.medium); + if (cpp_result.update_index.has_value()) { + proto_result.set_update_index(cpp_result.update_index.value()); + } + proto_result.set_result_category(cpp_result.result_category); + proto_result.set_result_code(cpp_result.result_code); + if (cpp_result.connection_mode.has_value()) { + proto_result.set_connection_mode(cpp_result.connection_mode.value()); + } + return proto_result; +} + +} // namespace + +AnalyticsRecorderImpl::AnalyticsRecorderImpl(EventLogger* event_logger) + : event_logger_(event_logger) { + VLOG(1) << "Start AnalyticsRecorderImpl ctor event_logger_=" << event_logger_; + LogStartSession(); +} + +AnalyticsRecorderImpl::~AnalyticsRecorderImpl() = default; + +bool AnalyticsRecorderImpl::IsSessionLogged() { + MutexLock lock(&mutex_); + return session_was_logged_; +} + +int AnalyticsRecorderImpl::GetLatestUpdateIndexLocked( + const std::vector& list) { + int latest_update_index = 0; + for (const auto& operation_result_with_medium : list) { + if (operation_result_with_medium.update_index() > latest_update_index) { + latest_update_index = operation_result_with_medium.update_index(); + } + } + return latest_update_index; +} + +void AnalyticsRecorderImpl::OnStartAdvertising( + connections::Strategy strategy, const std::vector& mediums, + AdvertisingMetadataParams* advertising_metadata_params) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStartAdvertising")) { + return; + } + if (!strategy.IsValid()) { + LOG(INFO) << "AnalyticsRecorderImpl OnStartAdvertising with unknown " + "strategy, bail out."; + return; + } + // Initialize/update a StrategySession. + UpdateStrategySessionLocked(strategy, ADVERTISER); + + // Initialize and set a AdvertisingPhase. + started_advertising_phase_time_ = SystemClock::ElapsedRealtime(); + current_advertising_phase_ = + std::make_unique(); + absl::c_copy(mediums, RepeatedFieldBackInserter( + current_advertising_phase_->mutable_medium())); + // Set a AdvertisingMetadata. + AdvertisingMetadataParams default_params = {}; + if (advertising_metadata_params == nullptr) { + advertising_metadata_params = &default_params; + } + if (!advertising_metadata_params->operation_result_with_mediums.empty()) { + for (const auto& cpp_result : + advertising_metadata_params->operation_result_with_mediums) { + *current_advertising_phase_->add_adv_dis_result() = + ConvertToProtoOperationResultWithMedium(cpp_result); + } + } + auto* advertising_metadata = + current_advertising_phase_->mutable_advertising_metadata(); + advertising_metadata->set_supports_extended_ble_advertisements( + advertising_metadata_params->is_extended_advertisement_supported); + advertising_metadata->set_connected_ap_frequency( + advertising_metadata_params->connected_ap_frequency); + advertising_metadata->set_supports_nfc_technology( + advertising_metadata_params->is_nfc_available); +} + +void AnalyticsRecorderImpl::OnStopAdvertising() { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStopAdvertising")) { + return; + } + RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ true); +} + +int AnalyticsRecorderImpl::GetNextAdvertisingUpdateIndex() { + MutexLock lock(&mutex_); + + if (current_advertising_phase_ == nullptr) { + return 0; + } + return GetLatestUpdateIndexLocked( + std::vector( + current_advertising_phase_->adv_dis_result().begin(), + current_advertising_phase_->adv_dis_result().end())) + + 1; +} + +void AnalyticsRecorderImpl::OnStartDiscovery( + connections::Strategy strategy, const std::vector& mediums, + DiscoveryMetadataParams* discovery_metadata_params) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStartDiscovery")) { + return; + } + if (!strategy.IsValid()) { + LOG(INFO) << "AnalyticsRecorderImpl OnStartDiscovery unknown " + "strategy enter, bail out."; + return; + } + + // Initialize/update a StrategySession. + UpdateStrategySessionLocked(strategy, DISCOVERER); + + // Initialize and set a DiscoveryPhase. + started_discovery_phase_time_ = SystemClock::ElapsedRealtime(); + current_discovery_phase_ = std::make_unique(); + absl::c_copy(mediums, RepeatedFieldBackInserter( + current_discovery_phase_->mutable_medium())); + // Set a DiscoveryMetadata. + DiscoveryMetadataParams default_params = {}; + if (discovery_metadata_params == nullptr) { + discovery_metadata_params = &default_params; + } + if (!discovery_metadata_params->operation_result_with_mediums.empty()) { + for (const auto& cpp_result : + discovery_metadata_params->operation_result_with_mediums) { + *current_discovery_phase_->add_adv_dis_result() = + ConvertToProtoOperationResultWithMedium(cpp_result); + } + } + auto* discovery_metadata = + current_discovery_phase_->mutable_discovery_metadata(); + discovery_metadata->set_supports_extended_ble_advertisements( + discovery_metadata_params->is_extended_advertisement_supported); + discovery_metadata->set_connected_ap_frequency( + discovery_metadata_params->connected_ap_frequency); + discovery_metadata->set_supports_nfc_technology( + discovery_metadata_params->is_nfc_available); +} + +void AnalyticsRecorderImpl::OnStopDiscovery() { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStopDiscovery")) { + return; + } + RecordDiscoveryPhaseDurationAndReasonLocked(/*on_stop=*/true); +} + +int AnalyticsRecorderImpl::GetNextDiscoveryUpdateIndex() { + MutexLock lock(&mutex_); + if (current_discovery_phase_ == nullptr) { + return 0; + } + return GetLatestUpdateIndexLocked( + std::vector( + current_discovery_phase_->adv_dis_result().begin(), + current_discovery_phase_->adv_dis_result().end())) + + 1; +} + +void AnalyticsRecorderImpl::OnStartedIncomingConnectionListening( + connections::Strategy strategy) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStartedIncomingConnectionListening")) { + return; + } + UpdateStrategySessionLocked(strategy, ADVERTISER); + if (started_advertising_phase_time_ == absl::InfinitePast()) { + started_advertising_phase_time_ = SystemClock::ElapsedRealtime(); + } +} + +void AnalyticsRecorderImpl::OnStoppedIncomingConnectionListening() { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnStoppedIncomingConnectionListening")) { + return; + } + RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); +} + +void AnalyticsRecorderImpl::OnEndpointFound(Medium medium) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnEndpointFound")) { + return; + } + if (current_discovery_phase_ == nullptr) { + LOG(INFO) << "Unable to record discovered endpoint due to null " + "current_discovery_phase_"; + return; + } + ConnectionsLog::DiscoveredEndpoint* discovered_endpoint = + current_discovery_phase_->add_discovered_endpoint(); + discovered_endpoint->set_medium(medium); + discovered_endpoint->set_latency_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_discovery_phase_time_)); +} + +void AnalyticsRecorderImpl::OnRequestConnection( + const connections::Strategy& strategy, const std::string& endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("onRequestConnection")) { + return; + } + + UpdateStrategySessionLocked(strategy, DISCOVERER); + if (started_discovery_phase_time_ == absl::InfinitePast()) { + started_discovery_phase_time_ = SystemClock::ElapsedRealtime(); + } +} + +void AnalyticsRecorderImpl::OnConnectionRequestReceived( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnConnectionRequestReceived")) { + return; + } + absl::Time current_time = SystemClock::ElapsedRealtime(); + auto connection_request = + std::make_unique(); + connection_request->set_duration_millis(absl::ToUnixMillis(current_time)); + connection_request->set_request_delay_millis(absl::ToInt64Milliseconds( + current_time - started_advertising_phase_time_)); + incoming_connection_requests_.insert( + {remote_endpoint_id, std::move(connection_request)}); +} + +void AnalyticsRecorderImpl::OnConnectionRequestSent( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnConnectionRequestSent")) { + return; + } + absl::Time current_time = SystemClock::ElapsedRealtime(); + auto connection_request = + std::make_unique(); + connection_request->set_duration_millis(absl::ToUnixMillis(current_time)); + connection_request->set_request_delay_millis( + absl::ToInt64Milliseconds(current_time - started_discovery_phase_time_)); + outgoing_connection_requests_.insert( + {remote_endpoint_id, std::move(connection_request)}); +} + +void AnalyticsRecorderImpl::OnRemoteEndpointAccepted( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnRemoteEndpointAccepted")) { + return; + } + RemoteEndpointRespondedLocked(remote_endpoint_id, ACCEPTED); +} + +void AnalyticsRecorderImpl::OnLocalEndpointAccepted( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnLocalEndpointAccepted")) { + return; + } + LocalEndpointRespondedLocked(remote_endpoint_id, ACCEPTED); +} + +void AnalyticsRecorderImpl::OnRemoteEndpointRejected( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnRemoteEndpointRejected")) { + return; + } + RemoteEndpointRespondedLocked(remote_endpoint_id, REJECTED); +} + +void AnalyticsRecorderImpl::OnLocalEndpointRejected( + const std::string& remote_endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnLocalEndpointRejected")) { + return; + } + LocalEndpointRespondedLocked(remote_endpoint_id, REJECTED); +} + +void AnalyticsRecorderImpl::OnIncomingConnectionAttempt( + ConnectionAttemptType type, Medium medium, ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnIncomingConnectionAttempt")) { + return; + } + if (current_strategy_session_ == nullptr) { + LOG(INFO) << "Unable to record incoming connection attempt due to " + "null current_strategy_session_"; + return; + } + + ConnectionAttemptMetadataParams default_params = {}; + if (connection_attempt_metadata_params == nullptr) { + connection_attempt_metadata_params = &default_params; + } + OnIncomingConnectionAttemptLocked(type, medium, result, duration, + connection_token, + connection_attempt_metadata_params); +} + +void AnalyticsRecorderImpl::OnIncomingConnectionAttemptLocked( + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { + auto* connection_attempt = + current_strategy_session_->add_connection_attempt(); + connection_attempt->set_duration_millis(absl::ToInt64Milliseconds(duration)); + connection_attempt->set_type(type); + connection_attempt->set_direction(INCOMING); + connection_attempt->set_medium(medium); + connection_attempt->set_attempt_result(result); + connection_attempt->set_connection_token(connection_token); + + auto* connection_attempt_metadata = + connection_attempt->mutable_connection_attempt_metadata(); + connection_attempt_metadata->set_technology( + connection_attempt_metadata_params->technology); + connection_attempt_metadata->set_band( + connection_attempt_metadata_params->band); + connection_attempt_metadata->set_frequency( + connection_attempt_metadata_params->frequency); + connection_attempt_metadata->set_network_operator( + connection_attempt_metadata_params->network_operator); + connection_attempt_metadata->set_country_code( + connection_attempt_metadata_params->country_code); + connection_attempt_metadata->set_frequency( + connection_attempt_metadata_params->frequency); + connection_attempt_metadata->set_is_tdls_used( + connection_attempt_metadata_params->is_tdls_used); + connection_attempt_metadata->set_wifi_hotspot_status( + connection_attempt_metadata_params->wifi_hotspot_enabled); + connection_attempt_metadata->set_try_counts( + connection_attempt_metadata_params->try_count); + connection_attempt_metadata->set_max_tx_speed( + connection_attempt_metadata_params->max_wifi_tx_speed); + connection_attempt_metadata->set_max_rx_speed( + connection_attempt_metadata_params->max_wifi_rx_speed); + connection_attempt_metadata->set_wifi_channel_width( + connection_attempt_metadata_params->channel_width); + + auto operation_result_proto = + std::make_unique(); + operation_result_proto->set_result_code( + connection_attempt_metadata_params->operation_result_code); + operation_result_proto->set_result_category(ConvertToOperationResultCategory( + connection_attempt_metadata_params->operation_result_code)); + connection_attempt->set_allocated_operation_result( + operation_result_proto.release()); +} + +void AnalyticsRecorderImpl::OnOutgoingConnectionAttempt( + const std::string& remote_endpoint_id, ConnectionAttemptType type, + Medium medium, ConnectionAttemptResult result, absl::Duration duration, + const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnOutgoingConnectionAttempt")) { + return; + } + if (current_strategy_session_ == nullptr) { + LOG(INFO) << "Unable to record outgoing connection attempt due to " + "null current_strategy_session_"; + return; + } + + ConnectionAttemptMetadataParams default_params = {}; + if (connection_attempt_metadata_params == nullptr) { + connection_attempt_metadata_params = &default_params; + } + + // For the case of transfer a big file and the upgrades always failure, then + // there will have repeating upgrade attempt and cause many same attempt value + // be log. So add a method to skip. + if (ConnectionAttemptResultCodeExistedLocked( + medium, OUTGOING, connection_token, type, + connection_attempt_metadata_params->operation_result_code)) { + return; + } + + OnOutgoingConnectionAttemptLocked(remote_endpoint_id, type, medium, result, + duration, connection_token, + connection_attempt_metadata_params); +} + +void AnalyticsRecorderImpl::OnOutgoingConnectionAttemptLocked( + const std::string& remote_endpoint_id, ConnectionAttemptType type, + Medium medium, ConnectionAttemptResult result, absl::Duration duration, + const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) { + auto* connection_attempt = + current_strategy_session_->add_connection_attempt(); + connection_attempt->set_duration_millis(absl::ToInt64Milliseconds(duration)); + connection_attempt->set_type(type); + connection_attempt->set_direction(OUTGOING); + connection_attempt->set_medium(medium); + connection_attempt->set_attempt_result(result); + connection_attempt->set_connection_token(connection_token); + + auto* connection_attempt_metadata = + connection_attempt->mutable_connection_attempt_metadata(); + connection_attempt_metadata->set_technology( + connection_attempt_metadata_params->technology); + connection_attempt_metadata->set_band( + connection_attempt_metadata_params->band); + connection_attempt_metadata->set_frequency( + connection_attempt_metadata_params->frequency); + connection_attempt_metadata->set_network_operator( + connection_attempt_metadata_params->network_operator); + connection_attempt_metadata->set_country_code( + connection_attempt_metadata_params->country_code); + connection_attempt_metadata->set_frequency( + connection_attempt_metadata_params->frequency); + connection_attempt_metadata->set_is_tdls_used( + connection_attempt_metadata_params->is_tdls_used); + connection_attempt_metadata->set_wifi_hotspot_status( + connection_attempt_metadata_params->wifi_hotspot_enabled); + connection_attempt_metadata->set_try_counts( + connection_attempt_metadata_params->try_count); + connection_attempt_metadata->set_max_tx_speed( + connection_attempt_metadata_params->max_wifi_tx_speed); + connection_attempt_metadata->set_max_rx_speed( + connection_attempt_metadata_params->max_wifi_rx_speed); + connection_attempt_metadata->set_wifi_channel_width( + connection_attempt_metadata_params->channel_width); + + auto operation_result_proto = + std::make_unique(); + operation_result_proto->set_result_code( + connection_attempt_metadata_params->operation_result_code); + operation_result_proto->set_result_category(ConvertToOperationResultCategory( + connection_attempt_metadata_params->operation_result_code)); + connection_attempt->set_allocated_operation_result( + operation_result_proto.release()); + + if (type == INITIAL && result != RESULT_SUCCESS) { + auto it = outgoing_connection_requests_.find(remote_endpoint_id); + if (it != outgoing_connection_requests_.end()) { + // An outgoing, initial ConnectionAttempt has a corresponding + // ConnectionRequest that, since the ConnectionAttempt has failed, will + // never be delivered to the advertiser. + auto pair = outgoing_connection_requests_.extract(it); + std::unique_ptr& connection_request = + pair.mapped(); + connection_request->set_local_response(NOT_SENT); + connection_request->set_remote_response(NOT_SENT); + UpdateDiscovererConnectionRequestLocked(connection_request.get()); + } + } +} + +void AnalyticsRecorderImpl::OnConnectionEstablished( + const std::string& endpoint_id, Medium medium, + const std::string& connection_token) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnConnectionEstablished")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it != active_connections_.end()) { + const std::unique_ptr& logical_connection = it->second; + logical_connection->PhysicalConnectionEstablished(medium, connection_token); + } else { + active_connections_.insert( + {endpoint_id, + std::make_unique(medium, connection_token)}); + } +} + +void AnalyticsRecorderImpl::OnConnectionClosed(const std::string& endpoint_id, + Medium medium, + DisconnectionReason reason, + SafeDisconnectionResult result) { + MutexLock lock(&mutex_); + LOG(INFO) << __func__ + << ": OnConnectionClosed is called with endpoint_id:" << endpoint_id + << ", medium:" << Medium_Name(medium) + << ", reason:" << DisconnectionReason_Name(reason) + << ", result:" << static_cast(result); + + if (!CanRecordAnalyticsLocked("OnConnectionClosed")) { + return; + } + + if (current_strategy_session_ == nullptr) { + VLOG(1) << "AnalyticsRecorderImpl CanRecordAnalytics Unexpected call " + << __func__ << " since current_strategy_session_ is required."; + return; + } + + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->PhysicalConnectionClosed(medium, reason, result); + if (reason != UPGRADED) { + // Unless this is an upgraded connection, remove this from our active + // connections. Any future communication with an endpoint will need to be + // re-established with a new ConnectionRequest. + auto pair = active_connections_.extract(it); + std::unique_ptr& logical_connection = pair.mapped(); + + absl::c_copy( + logical_connection->GetEstablisedConnections(), + RepeatedFieldBackInserter( + current_strategy_session_->mutable_established_connection())); + } +} + +void AnalyticsRecorderImpl::OnIncomingPayloadStarted( + const std::string& endpoint_id, std::int64_t payload_id, + connections::PayloadType type, std::int64_t total_size_bytes) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnIncomingPayloadStarted")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->IncomingPayloadStarted( + payload_id, PayloadTypeToProtoPayloadType(type), total_size_bytes); +} + +void AnalyticsRecorderImpl::OnPayloadChunkReceived( + const std::string& endpoint_id, std::int64_t payload_id, + std::int64_t chunk_size_bytes) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnPayloadChunkReceived")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->ChunkReceived(payload_id, chunk_size_bytes); +} + +void AnalyticsRecorderImpl::OnIncomingPayloadDone( + const std::string& endpoint_id, std::int64_t payload_id, + PayloadStatus status, OperationResultCode operation_result_code) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnIncomingPayloadDone")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->IncomingPayloadDone(payload_id, status, + operation_result_code); +} + +void AnalyticsRecorderImpl::OnOutgoingPayloadStarted( + const std::vector& endpoint_ids, std::int64_t payload_id, + connections::PayloadType type, std::int64_t total_size_bytes) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnOutgoingPayloadStarted")) { + return; + } + for (const auto& endpoint_id : endpoint_ids) { + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + continue; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->OutgoingPayloadStarted( + payload_id, PayloadTypeToProtoPayloadType(type), total_size_bytes); + } +} + +void AnalyticsRecorderImpl::OnPayloadChunkSent(const std::string& endpoint_id, + std::int64_t payload_id, + std::int64_t chunk_size_bytes) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnPayloadChunkSent")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + const std::unique_ptr& logical_connection = it->second; + logical_connection->ChunkSent(payload_id, chunk_size_bytes); +} + +void AnalyticsRecorderImpl::OnOutgoingPayloadDone( + const std::string& endpoint_id, std::int64_t payload_id, + PayloadStatus status, OperationResultCode operation_result_code) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnOutgoingPayloadDone")) { + return; + } + auto it = active_connections_.find(endpoint_id); + if (it == active_connections_.end()) { + return; + } + + const std::unique_ptr& logical_connection = it->second; + logical_connection->OutgoingPayloadDone(payload_id, status, + operation_result_code); +} + +void AnalyticsRecorderImpl::OnBandwidthUpgradeStarted( + const std::string& endpoint_id, Medium from_medium, Medium to_medium, + ConnectionAttemptDirection direction, const std::string& connection_token) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeStarted")) { + return; + } + auto bandwidth_upgrade_attempt = + std::make_unique(); + bandwidth_upgrade_attempt->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime())); + bandwidth_upgrade_attempt->set_from_medium(from_medium); + bandwidth_upgrade_attempt->set_to_medium(to_medium); + bandwidth_upgrade_attempt->set_direction(direction); + bandwidth_upgrade_attempt->set_connection_token(connection_token); + bandwidth_upgrade_attempts_.insert( + {endpoint_id, std::move(bandwidth_upgrade_attempt)}); +} + +void AnalyticsRecorderImpl::UpdateBwUpgradeNetworkInfo( + const std::string& endpoint_id, int num_interfaces, + int num_ipv6_only_interfaces) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("UpdateBwUpgradeNetworkInfo")) { + return; + } + auto it = bandwidth_upgrade_attempts_.find(endpoint_id); + if (it == bandwidth_upgrade_attempts_.end()) { + return; + } + ConnectionsLog::BandwidthUpgradeAttempt* bandwidth_upgrade_attempt = + it->second.get(); + bandwidth_upgrade_attempt->set_num_interfaces(num_interfaces); + bandwidth_upgrade_attempt->set_num_ipv6_only_interfaces( + num_ipv6_only_interfaces); +} + +void AnalyticsRecorderImpl::OnBandwidthUpgradeError( + const std::string& endpoint_id, BandwidthUpgradeResult result, + BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeError")) { + return; + } + // If the same records existed, drop this one. + if (EraseIfBandwidthUpgradeRecordExistedLocked( + endpoint_id, result, error_stage, operation_result_code)) { + return; + } + FinishUpgradeAttemptLocked(endpoint_id, result, error_stage, + operation_result_code); +} + +void AnalyticsRecorderImpl::OnBandwidthUpgradeSuccess( + const std::string& endpoint_id) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeSuccess")) { + return; + } + FinishUpgradeAttemptLocked(endpoint_id, UPGRADE_RESULT_SUCCESS, + UPGRADE_SUCCESS, + OperationResultCode::DETAIL_SUCCESS); +} + +void AnalyticsRecorderImpl::OnErrorCode(const ErrorCodeParams& params) { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("OnErrorCode")) { + return; + } + auto error_code = std::make_unique(); + error_code->set_medium(params.medium); + error_code->set_event(params.event); + error_code->set_connection_token(params.connection_token); + error_code->set_description(params.description); + + if (params.is_common_error) { + error_code->set_common_error(params.common_error); + } else { + switch (params.event) { + case location::nearby::errorcode::proto::START_ADVERTISING: + error_code->set_start_advertising_error(params.start_advertising_error); + break; + case location::nearby::errorcode::proto::STOP_ADVERTISING: + error_code->set_stop_advertising_error(params.stop_advertising_error); + break; + case location::nearby::errorcode::proto:: + START_LISTENING_INCOMING_CONNECTION: + error_code->set_start_listening_incoming_connection_error( + params.start_listening_incoming_connection_error); + break; + case location::nearby::errorcode::proto:: + STOP_LISTENING_INCOMING_CONNECTION: + error_code->set_stop_listening_incoming_connection_error( + params.stop_listening_incoming_connection_error); + break; + case location::nearby::errorcode::proto::START_DISCOVERING: + error_code->set_start_discovering_error(params.start_discovering_error); + break; + case location::nearby::errorcode::proto::STOP_DISCOVERING: + error_code->set_stop_discovering_error(params.stop_discovering_error); + break; + case location::nearby::errorcode::proto::CONNECT: + error_code->set_connect_error(params.connect_error); + break; + case location::nearby::errorcode::proto::DISCONNECT: + error_code->set_disconnect_error(params.disconnect_error); + break; + case location::nearby::errorcode::proto::UNKNOWN_EVENT: + default: + error_code->set_common_error(params.common_error); + break; + } + } + + ConnectionsLog connections_log; + connections_log.set_event_type(ERROR_CODE); + connections_log.set_version(kVersion); + connections_log.set_allocated_error_code(error_code.release()); + + VLOG(1) << "AnalyticsRecorderImpl LogErrorCode connections_log=" + << connections_log.DebugString(); // NOLINT + + event_logger_->Log(connections_log); +} + +void AnalyticsRecorderImpl::LogStartSession() { + MutexLock lock(&mutex_); + if (start_client_session_was_logged_) { + LOG(WARNING) << "AnalyticsRecorderImpl CanRecordAnalytics Unexpected call " + << kOnStartClientSession + << " after start client session has already been logged."; + return; + } + + session_was_logged_ = false; + if (CanRecordAnalyticsLocked(kOnStartClientSession)) { + client_session_ = std::make_unique(); + started_client_session_time_ = SystemClock::ElapsedRealtime(); + start_client_session_was_logged_ = true; + LogEvent(START_CLIENT_SESSION); + } +} + +void AnalyticsRecorderImpl::LogSession() { + MutexLock lock(&mutex_); + if (!CanRecordAnalyticsLocked("LogSession")) { + return; + } + FinishStrategySessionLocked(); + client_session_->set_duration_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_client_session_time_)); + LogClientSessionLocked(); + LogEvent(STOP_CLIENT_SESSION); + start_client_session_was_logged_ = false; + session_was_logged_ = true; +} + +bool AnalyticsRecorderImpl::CanRecordAnalyticsLocked( + absl::string_view method_name) { + VLOG(1) << "AnalyticsRecorderImpl LogEvent " << method_name << " is calling."; + if (event_logger_ == nullptr) { + return false; + } + + if (session_was_logged_) { + VLOG(1) << "AnalyticsRecorderImpl CanRecordAnalytics Unexpected call " + << method_name << " after session has already been logged."; + return false; + } + + return true; +} + +// TODO: b/391339677 - Investigate why we need to reset the resources. And +// verify in b/238375695 to see if we still meet the issue after removing the +// Reset function. +void AnalyticsRecorderImpl::LogClientSessionLocked() { + ConnectionsLog connections_log; + connections_log.set_event_type(CLIENT_SESSION); + connections_log.set_allocated_client_session(client_session_.release()); + connections_log.set_version(kVersion); + + VLOG(1) << "AnalyticsRecorderImpl LogClientSession connections_log=" + << connections_log.DebugString(); // NOLINT + + event_logger_->Log(connections_log); + client_session_ = nullptr; +} + +void AnalyticsRecorderImpl::LogEvent(EventType event_type) { + ConnectionsLog connections_log; + connections_log.set_event_type(event_type); + connections_log.set_version(kVersion); + + VLOG(1) << "AnalyticsRecorderImpl LogEvent connections_log=" + << connections_log.DebugString(); // NOLINT + + event_logger_->Log(connections_log); +} + +void AnalyticsRecorderImpl::UpdateStrategySessionLocked( + connections::Strategy strategy, SessionRole role) { + // If we're not switching strategies, just update the current StrategySession + // with the new role. + if (strategy == current_strategy_ && current_strategy_session_ != nullptr) { + if (absl::c_linear_search(current_strategy_session_->role(), role)) { + // We've already acted as this role before, so make sure we've finished + // recording the previous round. + switch (role) { + case ADVERTISER: + FinishAdvertisingPhaseLocked(); + break; + case DISCOVERER: + FinishDiscoveryPhaseLocked(); + break; + default: + break; + } + } else { + current_strategy_session_->add_role(role); + } + } else { + // Otherwise, we're starting a new Strategy. + current_strategy_ = strategy; + FinishStrategySessionLocked(); + LogEvent(START_STRATEGY_SESSION); + current_strategy_session_ = + std::make_unique(); + started_strategy_session_time_ = SystemClock::ElapsedRealtime(); + current_strategy_session_->set_strategy( + StrategyToConnectionStrategy(strategy)); + current_strategy_session_->add_role(role); + } +} + +void AnalyticsRecorderImpl::RecordAdvertisingPhaseDurationAndReasonLocked( + bool on_stop) const { + if (current_advertising_phase_ == nullptr) { + LOG(INFO) << "Unable to record advertising phase duration due to " + "null current_advertising_phase_"; + return; + } + if (!current_advertising_phase_->has_duration_millis()) { + current_advertising_phase_->set_duration_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_advertising_phase_time_)); + } + if (!current_advertising_phase_->has_stop_reason()) { + current_advertising_phase_->set_stop_reason( + on_stop ? StopAdvertisingReason::CLIENT_STOP_ADVERTISING + : StopAdvertisingReason::FINISH_SESSION_STOP_ADVERTISING); + } +} + +void AnalyticsRecorderImpl::FinishAdvertisingPhaseLocked() { + if (current_advertising_phase_ != nullptr) { + for (const auto& item : incoming_connection_requests_) { + // ConnectionRequests still pending have been ignored by the local or + // remote (or both) endpoints. + const std::unique_ptr& + connection_request = item.second; + MarkConnectionRequestIgnoredLocked(connection_request.get()); + UpdateAdvertiserConnectionRequestLocked(connection_request.get()); + } + RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); + if (current_strategy_session_ != nullptr) { + *current_strategy_session_->add_advertising_phase() = + *std::move(current_advertising_phase_); + } else { + LOG(INFO) << "Unable to record advertising phase due to null " + "current_strategy_session_"; + } + } + incoming_connection_requests_.clear(); +} + +void AnalyticsRecorderImpl::RecordDiscoveryPhaseDurationAndReasonLocked( + bool on_stop) const { + if (current_discovery_phase_ == nullptr) { + LOG(INFO) << "Unable to record discovery phase duration due to " + "null current_discovery_phase_"; + return; + } + if (!current_discovery_phase_->has_duration_millis()) { + current_discovery_phase_->set_duration_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_discovery_phase_time_)); + } + // If the stop reason haven't been set yet, then set it. + if (!current_discovery_phase_->has_stop_reason()) { + current_discovery_phase_->set_stop_reason( + on_stop ? StopDiscoveringReason::CLIENT_STOP_DISCOVERING + : StopDiscoveringReason::FINISH_SESSION_STOP_DISCOVERING); + } +} + +void AnalyticsRecorderImpl::FinishDiscoveryPhaseLocked() { + if (current_discovery_phase_ != nullptr) { + for (const auto& item : outgoing_connection_requests_) { + // ConnectionRequests still pending have been ignored by the local or + // remote (or both) endpoints. + const std::unique_ptr& + connection_request = item.second; + MarkConnectionRequestIgnoredLocked(connection_request.get()); + UpdateDiscovererConnectionRequestLocked(connection_request.get()); + } + RecordDiscoveryPhaseDurationAndReasonLocked(/* on_stop=*/false); + if (current_strategy_session_ != nullptr) { + *current_strategy_session_->add_discovery_phase() = + *std::move(current_discovery_phase_); + } else { + LOG(INFO) << "Unable to record discovery phase due to null " + "current_strategy_session_"; + } + } + outgoing_connection_requests_.clear(); +} + +bool AnalyticsRecorderImpl::UpdateAdvertiserConnectionRequestLocked( + ConnectionsLog::ConnectionRequest* request) { + if (current_advertising_phase_ == nullptr) { + LOG(INFO) << "Unable to record advertiser connection request due to null " + "current_advertising_phase_"; + return false; + } + if (BothEndpointsRespondedLocked(request)) { + request->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + request->duration_millis()); + *current_advertising_phase_->add_received_connection_request() = *request; + return true; + } + return false; +} + +bool AnalyticsRecorderImpl::UpdateDiscovererConnectionRequestLocked( + ConnectionsLog::ConnectionRequest* request) { + if (current_discovery_phase_ == nullptr) { + LOG(INFO) << "Unable to record discoverer connection request due " + "to null current_discovery_phase_."; + return false; + } + if (BothEndpointsRespondedLocked(request) || + request->local_response() == NOT_SENT) { + request->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + request->duration_millis()); + *current_discovery_phase_->add_sent_connection_request() = *request; + return true; + } + return false; +} + +bool AnalyticsRecorderImpl::BothEndpointsRespondedLocked( + ConnectionsLog::ConnectionRequest* request) { + return request->has_local_response() && request->has_remote_response(); +} + +void AnalyticsRecorderImpl::LocalEndpointRespondedLocked( + const std::string& remote_endpoint_id, ConnectionRequestResponse response) { + auto out = outgoing_connection_requests_.find(remote_endpoint_id); + if (out != outgoing_connection_requests_.end()) { + ConnectionsLog::ConnectionRequest* connection_request = out->second.get(); + connection_request->set_local_response(response); + if (UpdateDiscovererConnectionRequestLocked(connection_request)) { + outgoing_connection_requests_.erase(out); + } + } + auto in = incoming_connection_requests_.find(remote_endpoint_id); + if (in != incoming_connection_requests_.end()) { + ConnectionsLog::ConnectionRequest* connection_request = in->second.get(); + connection_request->set_local_response(response); + if (UpdateAdvertiserConnectionRequestLocked(connection_request)) { + incoming_connection_requests_.erase(in); + } + } +} + +void AnalyticsRecorderImpl::RemoteEndpointRespondedLocked( + const std::string& remote_endpoint_id, ConnectionRequestResponse response) { + auto out = outgoing_connection_requests_.find(remote_endpoint_id); + if (out != outgoing_connection_requests_.end()) { + ConnectionsLog::ConnectionRequest* connection_request = out->second.get(); + connection_request->set_remote_response(response); + if (UpdateDiscovererConnectionRequestLocked(connection_request)) { + outgoing_connection_requests_.erase(out); + } + } + auto in = incoming_connection_requests_.find(remote_endpoint_id); + if (in != incoming_connection_requests_.end()) { + ConnectionsLog::ConnectionRequest* connection_request = in->second.get(); + connection_request->set_remote_response(response); + if (UpdateAdvertiserConnectionRequestLocked(connection_request)) { + incoming_connection_requests_.erase(in); + } + } +} + +void AnalyticsRecorderImpl::MarkConnectionRequestIgnoredLocked( + ConnectionsLog::ConnectionRequest* request) { + if (!request->has_local_response()) { + request->set_local_response(IGNORED); + } + if (!request->has_remote_response()) { + request->set_remote_response(IGNORED); + } +} + +bool AnalyticsRecorderImpl::ConnectionAttemptResultCodeExistedLocked( + Medium medium, ConnectionAttemptDirection direction, + const std::string& connection_token, ConnectionAttemptType type, + OperationResultCode operation_result_code) { + if (current_strategy_session_ == nullptr || + current_strategy_session_->connection_attempt_size() == 0) { + return false; + } + for (auto& connection_attempt : + current_strategy_session_->connection_attempt()) { + if (connection_attempt.medium() == medium && + connection_attempt.direction() == direction && + connection_attempt.connection_token() == connection_token && + connection_attempt.type() == type && + connection_attempt.operation_result().result_code() == + operation_result_code) { + return true; + } + } + + return false; +} + +// If bandwidth upgrade always failed on the same fromMedium, toMedium, result, +// stage and result code, we'll drop the duplicate logs for preventing the waste +// of log storage space +bool AnalyticsRecorderImpl::EraseIfBandwidthUpgradeRecordExistedLocked( + const std::string& endpoint_id, BandwidthUpgradeResult result, + BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code) { + if (current_strategy_session_ == nullptr) { + return false; + } + auto it = bandwidth_upgrade_attempts_.find(endpoint_id); + if (it != bandwidth_upgrade_attempts_.end()) { + ConnectionsLog::BandwidthUpgradeAttempt* attempt = it->second.get(); + for (auto& existing_attempt : + current_strategy_session_->upgrade_attempt()) { + if (attempt->from_medium() == existing_attempt.from_medium() && + attempt->to_medium() == existing_attempt.to_medium() && + result == existing_attempt.upgrade_result() && + error_stage == existing_attempt.error_stage() && + operation_result_code == + existing_attempt.operation_result().result_code()) { + bandwidth_upgrade_attempts_.erase(it); + return true; + } + } + } + return false; +} + +void AnalyticsRecorderImpl::FinishUpgradeAttemptLocked( + const std::string& endpoint_id, BandwidthUpgradeResult result, + BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code, bool erase_item) { + if (current_strategy_session_ == nullptr) { + LOG(INFO) << "Unable to record upgrade attempt due to null " + "current_strategy_session_"; + return; + } + // Add the BandwidthUpgradeAttempt in the current StrategySession. + auto it = bandwidth_upgrade_attempts_.find(endpoint_id); + if (it != bandwidth_upgrade_attempts_.end()) { + ConnectionsLog::BandwidthUpgradeAttempt* attempt = it->second.get(); + attempt->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + attempt->duration_millis()); + attempt->set_error_stage(error_stage); + attempt->set_upgrade_result(result); + + auto operation_result_proto = + std::make_unique(); + operation_result_proto->set_result_code(operation_result_code); + operation_result_proto->set_result_category( + ConvertToOperationResultCategory(operation_result_code)); + attempt->set_allocated_operation_result(operation_result_proto.release()); + *current_strategy_session_->add_upgrade_attempt() = *attempt; + if (erase_item) { + bandwidth_upgrade_attempts_.erase(it); + } + } +} + +void AnalyticsRecorderImpl::FinishStrategySessionLocked() { + if (current_strategy_session_ != nullptr) { + FinishAdvertisingPhaseLocked(); + FinishDiscoveryPhaseLocked(); + + // Finish any unfinished LogicalConnections. + for (const auto& item : active_connections_) { + const std::unique_ptr& logical_connection = + item.second; + logical_connection->CloseAllPhysicalConnections(); + absl::c_copy( + logical_connection->GetEstablisedConnections(), + RepeatedFieldBackInserter( + current_strategy_session_->mutable_established_connection())); + } + active_connections_.clear(); + + // Finish any pending upgrade attempts. + for (const auto& item : bandwidth_upgrade_attempts_) { + FinishUpgradeAttemptLocked( + item.first, UNFINISHED_ERROR, UPGRADE_UNFINISHED, + OperationResultCode::DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS, + /*erase_item=*/false); + } + bandwidth_upgrade_attempts_.clear(); + + // Add the StrategySession in ClientSession + if (current_strategy_session_ != nullptr) { + current_strategy_session_->set_duration_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_strategy_session_time_)); + *client_session_->add_strategy_session() = + *std::move(current_strategy_session_); + } + + current_strategy_session_ = nullptr; + current_strategy_ = connections::Strategy::kNone; + LogEvent(STOP_STRATEGY_SESSION); + } +} + +ConnectionsStrategy AnalyticsRecorderImpl::StrategyToConnectionStrategy( + connections::Strategy strategy) { + if (strategy == connections::Strategy::kP2pCluster) { + return P2P_CLUSTER; + } + if (strategy == connections::Strategy::kP2pStar) { + return P2P_STAR; + } + if (strategy == connections::Strategy::kP2pPointToPoint) { + return P2P_POINT_TO_POINT; + } + return UNKNOWN_STRATEGY; +} + +PayloadType AnalyticsRecorderImpl::PayloadTypeToProtoPayloadType( + connections::PayloadType type) { + switch (type) { + case connections::PayloadType::kBytes: + return BYTES; + case connections::PayloadType::kFile: + return FILE; + case connections::PayloadType::kStream: + return STREAM; + default: + return UNKNOWN_PAYLOAD_TYPE; + } +} + +void AnalyticsRecorderImpl::PendingPayload::AddChunk( + std::int64_t chunk_size_bytes) { + num_bytes_transferred_ += chunk_size_bytes; + num_chunks_++; +} + +ConnectionsLog::Payload AnalyticsRecorderImpl::PendingPayload::GetProtoPayload( + PayloadStatus status) { + ConnectionsLog::Payload payload; + payload.set_duration_millis( + absl::ToInt64Milliseconds(SystemClock::ElapsedRealtime() - start_time_)); + payload.set_type(type_); + payload.set_total_size_bytes(total_size_bytes_); + payload.set_num_bytes_transferred(num_bytes_transferred_); + payload.set_num_chunks(num_chunks_); + payload.set_status(status); + + auto operation_result_proto = + std::make_unique(); + operation_result_proto->set_result_code(operation_result_code_); + operation_result_proto->set_result_category( + ConvertToOperationResultCategory(operation_result_code_)); + payload.set_allocated_operation_result(operation_result_proto.release()); + + return payload; +} + +void AnalyticsRecorderImpl::LogicalConnection::PhysicalConnectionEstablished( + Medium medium, const std::string& connection_token) { + if (current_medium_ != UNKNOWN_MEDIUM) { + LOG(WARNING) << "Unexpected call to PhysicalConnectionEstablished while " + "AnalyticsRecorderImpl still has an active current medium."; + } + + auto established_connection = + std::make_unique(); + established_connection->set_medium(medium); + established_connection->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime())); + established_connection->set_connection_token(connection_token); + + auto operation_result_proto = + std::make_unique(); + operation_result_proto->set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result_proto->set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + established_connection->set_allocated_operation_result( + operation_result_proto.release()); + physical_connections_.insert({medium, std::move(established_connection)}); + current_medium_ = medium; +} + +void AnalyticsRecorderImpl::LogicalConnection::PhysicalConnectionClosed( + Medium medium, DisconnectionReason reason, SafeDisconnectionResult result) { + if (current_medium_ == UNKNOWN_MEDIUM) { + LOG(WARNING) << "Unexpected call to PhysicalConnectionClosed() for medium " + << Medium_Name(medium) + << " while AnalyticsRecorderImpl has no active current medium"; + } else if (current_medium_ != medium) { + LOG(WARNING) << "Unexpected call to PhysicalConnectionClosed() for medium " + << Medium_Name(medium) + << "while AnalyticsRecorderImpl has active medium " + << Medium_Name(current_medium_); + } + + auto it = physical_connections_.find(medium); + if (it == physical_connections_.end()) { + LOG(WARNING) + << "Unexpected call to physicalConnectionClosed() for medium " + << Medium_Name(medium) + << " with no corresponding EstablishedConnection that was previously" + " opened."; + return; + } + ConnectionsLog::EstablishedConnection* established_connection = + it->second.get(); + if (established_connection->has_disconnection_reason()) { + LOG(WARNING) << "Unexpected call to physicalConnectionClosed() for medium " + << Medium_Name(medium) + << " which already has disconnection reason " + << DisconnectionReason_Name( + established_connection->disconnection_reason()); + return; + } + FinishPhysicalConnection(established_connection, reason, result); + + if (medium == current_medium_) { + // If the EstablishedConnection we just closed was the one that we have + // marked as current, unset currentMedium. + current_medium_ = UNKNOWN_MEDIUM; + } +} + +void AnalyticsRecorderImpl::LogicalConnection::CloseAllPhysicalConnections() { + for (const auto& physical_connection : physical_connections_) { + ConnectionsLog::EstablishedConnection* established_connection = + physical_connection.second.get(); + if (!established_connection->has_disconnection_reason()) { + FinishPhysicalConnection(established_connection, UNFINISHED, + SafeDisconnectionResult::kSafeDisconnection); + } + } + current_medium_ = UNKNOWN_MEDIUM; +} + +std::vector +AnalyticsRecorderImpl::LogicalConnection::GetEstablisedConnections() { + std::vector established_connections; + if (current_medium_ != UNKNOWN_MEDIUM) { + LOG(WARNING) + << "AnalyticsRecorderImpl expected no more active physical connections " + "before logging this endpoint connection."; + return established_connections; + } + std::transform(physical_connections_.begin(), physical_connections_.end(), + std::back_inserter(established_connections), + [](auto& kv) { return *kv.second; }); + physical_connections_.clear(); + + for (auto& established_connection : established_connections) { + if (absl::Milliseconds(established_connection.duration_millis()) >= + kConnectionTokenMaxLife) { + LOG(INFO) << "connection token exceed TTL, drop token."; + established_connection.set_connection_token(""); + } + } + + return established_connections; +} + +void AnalyticsRecorderImpl::LogicalConnection::IncomingPayloadStarted( + std::int64_t payload_id, PayloadType type, std::int64_t total_size_bytes) { + incoming_payloads_.insert( + {payload_id, std::make_unique(type, total_size_bytes)}); +} + +void AnalyticsRecorderImpl::LogicalConnection::ChunkReceived( + std::int64_t payload_id, std::int64_t size_bytes) { + auto it = incoming_payloads_.find(payload_id); + if (it == incoming_payloads_.end()) { + return; + } + PendingPayload* pending_payload = it->second.get(); + pending_payload->AddChunk(size_bytes); +} + +void AnalyticsRecorderImpl::LogicalConnection::IncomingPayloadDone( + std::int64_t payload_id, PayloadStatus status, + OperationResultCode operation_result_code) { + if (current_medium_ == UNKNOWN_MEDIUM) { + LOG(WARNING) << "Unexpected call to incomingPayloadDone() while " + "AnalyticsRecorderImpl has no active current medium."; + return; + } + auto it = physical_connections_.find(current_medium_); + if (it != physical_connections_.end()) { + const std::unique_ptr& + established_connection = it->second; + auto it = incoming_payloads_.find(payload_id); + if (it != incoming_payloads_.end()) { + it->second->SetOperationResultCode(operation_result_code); + *established_connection->add_received_payload() = + it->second->GetProtoPayload(status); + incoming_payloads_.erase(it); + } + } +} + +void AnalyticsRecorderImpl::LogicalConnection::OutgoingPayloadStarted( + std::int64_t payload_id, PayloadType type, std::int64_t total_size_bytes) { + outgoing_payloads_.insert( + {payload_id, std::make_unique(type, total_size_bytes)}); +} + +void AnalyticsRecorderImpl::LogicalConnection::ChunkSent( + std::int64_t payload_id, std::int64_t size_bytes) { + auto it = outgoing_payloads_.find(payload_id); + if (it == outgoing_payloads_.end()) { + return; + } + PendingPayload* payload = it->second.get(); + payload->AddChunk(size_bytes); +} + +void AnalyticsRecorderImpl::LogicalConnection::OutgoingPayloadDone( + std::int64_t payload_id, PayloadStatus status, + OperationResultCode operation_result_code) { + if (current_medium_ == UNKNOWN_MEDIUM) { + LOG(WARNING) << "Unexpected call to outgoingPayloadDone() while " + "AnalyticsRecorderImpl has no active current medium."; + return; + } + auto it = physical_connections_.find(current_medium_); + if (it != physical_connections_.end()) { + const std::unique_ptr& + established_connection = it->second; + auto it = outgoing_payloads_.find(payload_id); + if (it != outgoing_payloads_.end()) { + it->second->SetOperationResultCode(operation_result_code); + *established_connection->add_sent_payload() = + it->second->GetProtoPayload(status); + outgoing_payloads_.erase(it); + } + } +} + +void AnalyticsRecorderImpl::LogicalConnection::FinishPhysicalConnection( + ConnectionsLog::EstablishedConnection* established_connection, + DisconnectionReason reason, SafeDisconnectionResult result) { + established_connection->set_disconnection_reason(reason); + established_connection->set_safe_disconnection_result( + ConvertToProtoSafeDisconnectionResult(result)); + established_connection->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + established_connection->duration_millis()); + + // Add any not-yet-finished payloads to this EstablishedConnection. + std::vector in_payloads = + ResolvePendingPayloads(incoming_payloads_, reason); + absl::c_move(in_payloads, + RepeatedFieldBackInserter( + established_connection->mutable_received_payload())); + std::vector out_payloads = + ResolvePendingPayloads(outgoing_payloads_, reason); + absl::c_move(out_payloads, + RepeatedFieldBackInserter( + established_connection->mutable_sent_payload())); +} + +std::vector +AnalyticsRecorderImpl::LogicalConnection::ResolvePendingPayloads( + absl::btree_map>& + pending_payloads, + DisconnectionReason reason) { + std::vector completed_payloads; + absl::btree_map> + upgraded_payloads; + PayloadStatus status = + reason == UPGRADED ? MOVED_TO_NEW_MEDIUM : CONNECTION_CLOSED; + + OperationResultCode operation_result_code = + GetPendingPayloadResultCodeFromReason(reason); + for (const auto& item : pending_payloads) { + const std::unique_ptr& pending_payload = item.second; + pending_payload->SetOperationResultCode(operation_result_code); + ConnectionsLog::Payload proto_payload = + pending_payload->GetProtoPayload(status); + completed_payloads.push_back(proto_payload); + if (reason == UPGRADED) { + upgraded_payloads.insert( + {item.first, + std::make_unique(pending_payload->type(), + pending_payload->total_size_bytes(), + operation_result_code)}); + } + } + pending_payloads.clear(); + + if (reason == UPGRADED) { + // Re-populate the map with a new PendingPayload for each pending payload, + // since we expect them to be completed on the next EstablishedConnection. + pending_payloads = std::move(upgraded_payloads); + } + // Return the list of completed payloads to be added to the current + // EstablishedConnection. + return completed_payloads; +} + +OperationResultCode +AnalyticsRecorderImpl::LogicalConnection::GetPendingPayloadResultCodeFromReason( + DisconnectionReason reason) { + switch (reason) { + case UPGRADED: + return OperationResultCode::MISCELLEANEOUS_MOVE_TO_NEW_MEDIUM; + case DisconnectionReason::LOCAL_DISCONNECTION: + return OperationResultCode::CLIENT_CANCELLATION_LOCAL_DISCONNECT; + case DisconnectionReason::REMOTE_DISCONNECTION: + return OperationResultCode::CLIENT_CANCELLATION_REMOTE_DISCONNECT; + default: + return OperationResultCode::NEARBY_GENERIC_CONNECTION_CLOSED; + } +} + +OperationResultCategory AnalyticsRecorderImpl::GetOperationResultCategory( + location::nearby::proto::connections::OperationResultCode result_code) { + return ConvertToOperationResultCategory(result_code); +} + +void AnalyticsRecorderImpl::Sync() { MutexLock lock(&mutex_); } + +} // namespace nearby::analytics diff --git a/connections/implementation/analytics/analytics_recorder_impl.h b/connections/implementation/analytics/analytics_recorder_impl.h new file mode 100644 index 00000000..dfe0a342 --- /dev/null +++ b/connections/implementation/analytics/analytics_recorder_impl.h @@ -0,0 +1,459 @@ +// Copyright 2022-2023 Google LLC +// +// 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 +// +// https://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. + +#ifndef ANALYTICS_ANALYTICS_RECORDER_IMPL_H_ +#define ANALYTICS_ANALYTICS_RECORDER_IMPL_H_ + +#include +#include +#include +#include +#include + +#include "absl/base/thread_annotations.h" +#include "absl/container/btree_map.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" +#include "connections/implementation/analytics/advertising_metadata_params.h" +#include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/connection_attempt_metadata_params.h" +#include "connections/implementation/analytics/discovery_metadata_params.h" +#include "connections/payload_type.h" +#include "connections/strategy.h" +#include "internal/analytics/event_logger.h" +#include "internal/platform/error_code_params.h" +#include "internal/platform/implementation/system_clock.h" +#include "internal/platform/mutex.h" +#include "internal/proto/analytics/connections_log.pb.h" +#include "proto/connections_enums.pb.h" + +namespace nearby::analytics { + +class AnalyticsRecorderImpl : public AnalyticsRecorder { + public: + explicit AnalyticsRecorderImpl( + ::nearby::analytics::EventLogger* event_logger); + ~AnalyticsRecorderImpl() override; + + // Advertising phase + void OnStartAdvertising( + connections::Strategy strategy, + const std::vector& mediums, + AdvertisingMetadataParams* advertising_metadata_params) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnStopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_); + + int GetNextAdvertisingUpdateIndex() override ABSL_LOCKS_EXCLUDED(mutex_); + + // Connection listening + void OnStartedIncomingConnectionListening( + connections::Strategy strategy) override ABSL_LOCKS_EXCLUDED(mutex_); + void OnStoppedIncomingConnectionListening() override + ABSL_LOCKS_EXCLUDED(mutex_); + + // Discovery phase + void OnStartDiscovery( + connections::Strategy strategy, + const std::vector& mediums, + DiscoveryMetadataParams* discovery_metadata_params) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnStopDiscovery() override ABSL_LOCKS_EXCLUDED(mutex_); + + int GetNextDiscoveryUpdateIndex() override ABSL_LOCKS_EXCLUDED(mutex_); + void OnEndpointFound(location::nearby::proto::connections::Medium medium) + override ABSL_LOCKS_EXCLUDED(mutex_); + + // Connection request + void OnRequestConnection(const connections::Strategy& strategy, + const std::string& endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + + void OnConnectionRequestReceived(const std::string& remote_endpoint_id) + override ABSL_LOCKS_EXCLUDED(mutex_); + void OnConnectionRequestSent(const std::string& remote_endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnRemoteEndpointAccepted(const std::string& remote_endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnLocalEndpointAccepted(const std::string& remote_endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnRemoteEndpointRejected(const std::string& remote_endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnLocalEndpointRejected(const std::string& remote_endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + + // Connection attempt + void OnIncomingConnectionAttempt( + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) + override ABSL_LOCKS_EXCLUDED(mutex_); + void OnOutgoingConnectionAttempt( + const std::string& remote_endpoint_id, + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) + override ABSL_LOCKS_EXCLUDED(mutex_); + + // Connection established + void OnConnectionEstablished( + const std::string& endpoint_id, + location::nearby::proto::connections::Medium medium, + const std::string& connection_token) override ABSL_LOCKS_EXCLUDED(mutex_); + void OnConnectionClosed( + const std::string& endpoint_id, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::DisconnectionReason reason, + SafeDisconnectionResult result) override ABSL_LOCKS_EXCLUDED(mutex_); + + // Payload + void OnIncomingPayloadStarted(const std::string& endpoint_id, + std::int64_t payload_id, + connections::PayloadType type, + std::int64_t total_size_bytes) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnPayloadChunkReceived(const std::string& endpoint_id, + std::int64_t payload_id, + std::int64_t chunk_size_bytes) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnIncomingPayloadDone( + const std::string& endpoint_id, std::int64_t payload_id, + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code) override ABSL_LOCKS_EXCLUDED(mutex_); + void OnOutgoingPayloadStarted(const std::vector& endpoint_ids, + std::int64_t payload_id, + connections::PayloadType type, + std::int64_t total_size_bytes) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnPayloadChunkSent(const std::string& endpoint_id, + std::int64_t payload_id, + std::int64_t chunk_size_bytes) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnOutgoingPayloadDone( + const std::string& endpoint_id, std::int64_t payload_id, + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code) override ABSL_LOCKS_EXCLUDED(mutex_); + + // BandwidthUpgrade + void OnBandwidthUpgradeStarted( + const std::string& endpoint_id, + location::nearby::proto::connections::Medium from_medium, + location::nearby::proto::connections::Medium to_medium, + location::nearby::proto::connections::ConnectionAttemptDirection + direction, + const std::string& connection_token) override ABSL_LOCKS_EXCLUDED(mutex_); + void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id, + int num_interfaces, + int num_ipv6_only_interfaces) override + ABSL_LOCKS_EXCLUDED(mutex_); + void OnBandwidthUpgradeError( + const std::string& endpoint_id, + location::nearby::proto::connections::BandwidthUpgradeResult result, + location::nearby::proto::connections::BandwidthUpgradeErrorStage + error_stage, + location::nearby::proto::connections::OperationResultCode + operation_result_code) override ABSL_LOCKS_EXCLUDED(mutex_); + void OnBandwidthUpgradeSuccess(const std::string& endpoint_id) override + ABSL_LOCKS_EXCLUDED(mutex_); + + // Error Code + void OnErrorCode(const ErrorCodeParams& params) override; + + void LogStartSession() override ABSL_LOCKS_EXCLUDED(mutex_); + void LogSession() override ABSL_LOCKS_EXCLUDED(mutex_); + + bool IsSessionLogged() override; + + location::nearby::proto::connections::OperationResultCategory + GetOperationResultCategory( + location::nearby::proto::connections::OperationResultCode result_code) + override; + + void Sync() override; + + private: + // Tracks the chunks and duration of a Payload on a particular medium. + class PendingPayload { + public: + PendingPayload(location::nearby::proto::connections::PayloadType type, + std::int64_t total_size_bytes) + : PendingPayload(type, total_size_bytes, + location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN) {} + PendingPayload(location::nearby::proto::connections::PayloadType type, + std::int64_t total_size_bytes, + location::nearby::proto::connections::OperationResultCode + operation_result_code) + : start_time_(SystemClock::ElapsedRealtime()), + type_(type), + total_size_bytes_(total_size_bytes), + num_bytes_transferred_(0), + num_chunks_(0), + operation_result_code_(operation_result_code) {} + ~PendingPayload() = default; + + void AddChunk(std::int64_t chunk_size_bytes); + + location::nearby::analytics::proto::ConnectionsLog::Payload GetProtoPayload( + location::nearby::proto::connections::PayloadStatus status); + + location::nearby::proto::connections::PayloadType type() const { + return type_; + } + + std::int64_t total_size_bytes() const { return total_size_bytes_; } + + void SetOperationResultCode( + location::nearby::proto::connections::OperationResultCode + operation_result_code) { + operation_result_code_ = operation_result_code; + } + + private: + absl::Time start_time_; + location::nearby::proto::connections::PayloadType type_; + std::int64_t total_size_bytes_; + std::int64_t num_bytes_transferred_; + int num_chunks_; + location::nearby::proto::connections::OperationResultCode + operation_result_code_ = location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN; + }; + + class LogicalConnection { + public: + LogicalConnection( + location::nearby::proto::connections::Medium initial_medium, + const std::string& connection_token) { + PhysicalConnectionEstablished(initial_medium, connection_token); + } + LogicalConnection(const LogicalConnection&) = delete; + LogicalConnection(LogicalConnection&& other) + : current_medium_(std::move(other.current_medium_)), + physical_connections_(std::move(other.physical_connections_)), + incoming_payloads_(std::move(other.incoming_payloads_)), + outgoing_payloads_(std::move(other.outgoing_payloads_)) {} + LogicalConnection& operator=(const LogicalConnection&) = delete; + LogicalConnection&& operator=(LogicalConnection&&) = delete; + ~LogicalConnection() = default; + + void PhysicalConnectionEstablished( + location::nearby::proto::connections::Medium medium, + const std::string& connection_token); + void PhysicalConnectionClosed( + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::DisconnectionReason reason, + SafeDisconnectionResult result); + void CloseAllPhysicalConnections(); + + void IncomingPayloadStarted( + std::int64_t payload_id, + location::nearby::proto::connections::PayloadType type, + std::int64_t total_size_bytes); + void ChunkReceived(std::int64_t payload_id, std::int64_t size_bytes); + void IncomingPayloadDone( + std::int64_t payload_id, + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); + void OutgoingPayloadStarted( + std::int64_t payload_id, + location::nearby::proto::connections::PayloadType type, + std::int64_t total_size_bytes); + void ChunkSent(std::int64_t payload_id, std::int64_t size_bytes); + void OutgoingPayloadDone( + std::int64_t payload_id, + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); + + std::vector + GetEstablisedConnections(); + + private: + void FinishPhysicalConnection( + location::nearby::analytics::proto::ConnectionsLog:: + EstablishedConnection* established_connection, + location::nearby::proto::connections::DisconnectionReason reason, + SafeDisconnectionResult result); + std::vector + ResolvePendingPayloads( + absl::btree_map>& + pending_payloads, + location::nearby::proto::connections::DisconnectionReason reason); + location::nearby::proto::connections::OperationResultCode + GetPendingPayloadResultCodeFromReason( + location::nearby::proto::connections::DisconnectionReason reason); + + location::nearby::proto::connections::Medium current_medium_ = + location::nearby::proto::connections::UNKNOWN_MEDIUM; + absl::btree_map> + physical_connections_; + absl::btree_map> + incoming_payloads_; + absl::btree_map> + outgoing_payloads_; + }; + + bool CanRecordAnalyticsLocked(absl::string_view method_name) + ABSL_SHARED_LOCKS_REQUIRED(mutex_); + + // Callbacks the ConnectionsLog proto byte array data to the EventLogger with + // ClientSession sub-proto. + void LogClientSessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + // Callbacks the ConnectionsLog proto byte array data to the EventLogger. + void LogEvent(location::nearby::proto::connections::EventType event_type); + + void UpdateStrategySessionLocked( + connections::Strategy strategy, + location::nearby::proto::connections::SessionRole role) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void RecordAdvertisingPhaseDurationAndReasonLocked(bool on_stop) const + ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void FinishAdvertisingPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void RecordDiscoveryPhaseDurationAndReasonLocked(bool on_stop) const + ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void FinishDiscoveryPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool UpdateAdvertiserConnectionRequestLocked( + location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* + request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + bool UpdateDiscovererConnectionRequestLocked( + location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* + request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + bool BothEndpointsRespondedLocked( + location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* + request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void LocalEndpointRespondedLocked( + const std::string& remote_endpoint_id, + location::nearby::proto::connections::ConnectionRequestResponse response) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void RemoteEndpointRespondedLocked( + const std::string& remote_endpoint_id, + location::nearby::proto::connections::ConnectionRequestResponse response) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void MarkConnectionRequestIgnoredLocked( + location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest* + request) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void OnIncomingConnectionAttemptLocked( + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) + ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void OnOutgoingConnectionAttemptLocked( + const std::string& remote_endpoint_id, + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptResult result, + absl::Duration duration, const std::string& connection_token, + ConnectionAttemptMetadataParams* connection_attempt_metadata_params) + ABSL_SHARED_LOCKS_REQUIRED(mutex_); + bool ConnectionAttemptResultCodeExistedLocked( + location::nearby::proto::connections::Medium medium, + location::nearby::proto::connections::ConnectionAttemptDirection + direction, + const std::string& connection_token, + location::nearby::proto::connections::ConnectionAttemptType type, + location::nearby::proto::connections::OperationResultCode + operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + bool EraseIfBandwidthUpgradeRecordExistedLocked( + const std::string& endpoint_id, + location::nearby::proto::connections::BandwidthUpgradeResult result, + location::nearby::proto::connections::BandwidthUpgradeErrorStage + error_stage, + location::nearby::proto::connections::OperationResultCode + operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void FinishUpgradeAttemptLocked( + const std::string& endpoint_id, + location::nearby::proto::connections::BandwidthUpgradeResult result, + location::nearby::proto::connections::BandwidthUpgradeErrorStage + error_stage, + location::nearby::proto::connections::OperationResultCode + operation_result_code, + bool erase_item = true) ABSL_SHARED_LOCKS_REQUIRED(mutex_); + void FinishStrategySessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + int GetLatestUpdateIndexLocked( + const std::vector& list) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + location::nearby::proto::connections::ConnectionsStrategy + StrategyToConnectionStrategy(connections::Strategy strategy); + location::nearby::proto::connections::PayloadType + PayloadTypeToProtoPayloadType(connections::PayloadType type); + + // Not owned by AnalyticsRecorderImpl. Pointer must refer to a valid object + // that outlives the one constructed. + ::nearby::analytics::EventLogger* event_logger_; + + // Protects all sub-protos reading and writing in ConnectionLog. + Mutex mutex_; + + // ClientSession + std::unique_ptr< + location::nearby::analytics::proto::ConnectionsLog::ClientSession> + client_session_; + absl::Time started_client_session_time_; + bool session_was_logged_ ABSL_GUARDED_BY(mutex_) = false; + bool start_client_session_was_logged_ ABSL_GUARDED_BY(mutex_) = false; + + // Current StrategySession + connections::Strategy current_strategy_ ABSL_GUARDED_BY(mutex_) = + connections::Strategy::kNone; + std::unique_ptr< + location::nearby::analytics::proto::ConnectionsLog::StrategySession> + current_strategy_session_ ABSL_GUARDED_BY(mutex_); + absl::Time started_strategy_session_time_ ABSL_GUARDED_BY(mutex_); + + // Current AdvertisingPhase + std::unique_ptr< + location::nearby::analytics::proto::ConnectionsLog::AdvertisingPhase> + current_advertising_phase_; + absl::Time started_advertising_phase_time_ = absl::InfinitePast(); + + // Current DiscoveryPhase + std::unique_ptr< + location::nearby::analytics::proto::ConnectionsLog::DiscoveryPhase> + current_discovery_phase_; + absl::Time started_discovery_phase_time_ = absl::InfinitePast(); + + absl::btree_map> + incoming_connection_requests_ ABSL_GUARDED_BY(mutex_); + absl::btree_map> + outgoing_connection_requests_ ABSL_GUARDED_BY(mutex_); + absl::btree_map> + active_connections_ ABSL_GUARDED_BY(mutex_); + absl::btree_map> + bandwidth_upgrade_attempts_ ABSL_GUARDED_BY(mutex_); +}; + +} // namespace nearby::analytics + +#endif // ANALYTICS_ANALYTICS_RECORDER_IMPL_H_ diff --git a/connections/implementation/analytics/analytics_recorder_test.cc b/connections/implementation/analytics/analytics_recorder_impl_test.cc similarity index 97% rename from connections/implementation/analytics/analytics_recorder_test.cc rename to connections/implementation/analytics/analytics_recorder_impl_test.cc index 5b46b4ea..53bf6afe 100644 --- a/connections/implementation/analytics/analytics_recorder_test.cc +++ b/connections/implementation/analytics/analytics_recorder_impl_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/analytics_recorder_impl.h" #include @@ -26,7 +26,9 @@ #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "connections/payload_type.h" #include "connections/strategy.h" #include "internal/analytics/mock_event_logger.h" @@ -36,14 +38,13 @@ #include "internal/platform/exception.h" #include "internal/platform/medium_environment.h" #include "internal/proto/analytics/connections_log.proto.h" -#include "internal/test/fake_clock.h" #include "proto/connections_enums.proto.h" -namespace nearby { -namespace analytics { +namespace nearby::analytics { namespace { using ::location::nearby::analytics::proto::ConnectionsLog; +using SafeDisconnectionResult = nearby::analytics::SafeDisconnectionResult; using ::location::nearby::errorcode::proto::DISCONNECT; using ::location::nearby::errorcode::proto::DISCONNECT_NETWORK_FAILED; using ::location::nearby::errorcode::proto::INVALID_PARAMETER; @@ -158,7 +159,7 @@ class AnalyticsRecorderTest : public ::testing::Test { TEST_F(AnalyticsRecorderTest, SessionOnlyLoggedOnceWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); analytics_recorder.LogSession(); analytics_recorder.LogSession(); @@ -175,9 +176,9 @@ TEST_F(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedAdvertisingCalls) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -251,14 +252,14 @@ TEST_F(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedDiscoveryCalls) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( OperationResultCategory::CATEGORY_SUCCESS); - ConnectionsLog::OperationResultWithMedium operation_result2; + OperationResultWithMedium operation_result2; operation_result2.set_medium(BLE); operation_result2.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result2.set_result_category( @@ -350,7 +351,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -482,9 +483,9 @@ TEST_F(AnalyticsRecorderTest, AdvertiserConnectionRequestsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLE); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -586,9 +587,9 @@ TEST_F(AnalyticsRecorderTest, DiscoveryConnectionRequestsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -691,9 +692,9 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -781,9 +782,9 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -866,9 +867,9 @@ TEST_F(AnalyticsRecorderTest, TEST_F(AnalyticsRecorderTest, SuccessfulIncomingConnectionAttempt) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); - ConnectionsLog::OperationResultWithMedium operation_result; + OperationResultWithMedium operation_result; operation_result.set_medium(BLUETOOTH); operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); operation_result.set_result_category( @@ -957,7 +958,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto connections_attempt_metadata_params = analytics_recorder.BuildConnectionAttemptMetadataParams( @@ -1049,7 +1050,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -1061,9 +1062,8 @@ TEST_F(AnalyticsRecorderTest, analytics_recorder.OnConnectionEstablished(endpoint_id, BLUETOOTH, connection_token); MediumEnvironment::Instance().FastForward(absl::Milliseconds(300)); - analytics_recorder.OnConnectionClosed( - endpoint_id, BLUETOOTH, UPGRADED, - ConnectionsLog::EstablishedConnection::UNKNOWN_SAFE_DISCONNECTION_RESULT); + analytics_recorder.OnConnectionClosed(endpoint_id, BLUETOOTH, UPGRADED, + SafeDisconnectionResult::kUnknown); MediumEnvironment::Instance().FastForward(absl::Milliseconds(400)); analytics_recorder.OnConnectionEstablished(endpoint_id, WIFI_LAN, connection_token); @@ -1125,7 +1125,7 @@ TEST_F(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -1146,7 +1146,7 @@ TEST_F(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { MediumEnvironment::Instance().FastForward(absl::Milliseconds(600)); analytics_recorder.OnConnectionClosed( endpoint_id, BLUETOOTH, UPGRADED, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); MediumEnvironment::Instance().FastForward(absl::Milliseconds(700)); analytics_recorder.OnConnectionEstablished(endpoint_id, WIFI_LAN, connection_token); @@ -1162,7 +1162,7 @@ TEST_F(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { MediumEnvironment::Instance().FastForward(absl::Milliseconds(1200)); analytics_recorder.OnConnectionClosed( endpoint_id, WIFI_LAN, LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); MediumEnvironment::Instance().FastForward(absl::Milliseconds(1300)); analytics_recorder.LogSession(); @@ -1246,7 +1246,7 @@ TEST_F(AnalyticsRecorderTest, UpgradeAttemptWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -1350,7 +1350,7 @@ TEST_F(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); MediumEnvironment::Instance().FastForward(absl::Milliseconds(100)); analytics_recorder.OnStartedIncomingConnectionListening( @@ -1418,7 +1418,7 @@ TEST_F(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { TEST_F(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectly) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto discovery_metadata_params = analytics_recorder.BuildDiscoveryMetadataParams(); @@ -1452,7 +1452,7 @@ TEST_F(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForUnknownDescription) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto discovery_metadata_params = analytics_recorder.BuildDiscoveryMetadataParams(); @@ -1488,7 +1488,7 @@ TEST_F(AnalyticsRecorderTest, TEST_F(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForCommonError) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto discovery_metadata_params = analytics_recorder.BuildDiscoveryMetadataParams(); @@ -1521,7 +1521,7 @@ TEST_F(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForCommonError) { TEST_F(AnalyticsRecorderTest, CheckIfSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); MediumEnvironment::Instance().FastForward(absl::Milliseconds(100)); // LogSession to count down client_session_done_latch. @@ -1538,7 +1538,7 @@ TEST_F(AnalyticsRecorderTest, ConstructAnalyticsRecorder) { &start_client_session_done_latch); // Call the constructor to count down the session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); std::vector event_types = event_logger.GetLoggedEventTypes(); @@ -1555,7 +1555,7 @@ TEST_F( &start_client_session_done_latch); // Call the constructor to count down the start_client_session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); // Log start client session once. @@ -1584,7 +1584,7 @@ TEST_F(AnalyticsRecorderTest, &start_client_session_done_latch); // Call the constructor to count down the start_client_session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); // Log start client session once. @@ -1621,7 +1621,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -1753,7 +1753,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto discovery_metadata_params = analytics_recorder.BuildDiscoveryMetadataParams(); @@ -1887,7 +1887,7 @@ TEST_F(AnalyticsRecorderTest, ClearcActiveConnectionsAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -2010,7 +2010,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -2202,7 +2202,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -2256,7 +2256,7 @@ TEST_F(AnalyticsRecorderTest, NotLogSameStrategySessionProtoAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); // Via OnStartAdvertising, current_strategy_session_is set in // UpdateStrategySessionLocked. @@ -2323,7 +2323,7 @@ TEST_F(AnalyticsRecorderTest, NotLogDuplicateAdvertisingPhaseAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto advertising_metadata_params = analytics_recorder.BuildAdvertisingMetadataParams(); @@ -2418,7 +2418,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); auto discovery_metadata_params = analytics_recorder.BuildDiscoveryMetadataParams( @@ -2517,7 +2517,7 @@ TEST_F(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorderImpl analytics_recorder(&event_logger); // via OnStartAdvertising, current_strategy_session_ is set in // UpdateStrategySessionLocked. @@ -2566,7 +2566,7 @@ TEST_F(AnalyticsRecorderTest, MediumEnvironment::Instance().FastForward(absl::Milliseconds(500)); analytics_recorder.OnConnectionClosed( endpoint_id, BLUETOOTH, UPGRADED, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); MediumEnvironment::Instance().FastForward(absl::Milliseconds(600)); analytics_recorder.LogSession(); @@ -2576,5 +2576,4 @@ TEST_F(AnalyticsRecorderTest, } } // namespace -} // namespace analytics -} // namespace nearby +} // namespace nearby::analytics diff --git a/connections/implementation/analytics/discovery_metadata_params.h b/connections/implementation/analytics/discovery_metadata_params.h index 6442b03c..b90b2703 100644 --- a/connections/implementation/analytics/discovery_metadata_params.h +++ b/connections/implementation/analytics/discovery_metadata_params.h @@ -17,7 +17,7 @@ #include -#include "internal/proto/analytics/connections_log.pb.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" namespace nearby { @@ -26,8 +26,7 @@ struct DiscoveryMetadataParams { bool is_extended_advertisement_supported = false; int connected_ap_frequency = 0; bool is_nfc_available = false; - std::vector + std::vector operation_result_with_mediums = {}; }; diff --git a/connections/implementation/analytics/operation_result_with_medium.h b/connections/implementation/analytics/operation_result_with_medium.h new file mode 100644 index 00000000..483acc14 --- /dev/null +++ b/connections/implementation/analytics/operation_result_with_medium.h @@ -0,0 +1,55 @@ +// Copyright 2026 Google LLC +// +// 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 +// +// https://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. + +#ifndef ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_ +#define ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_ + +#include + +#include "proto/connections_enums.pb.h" + +namespace nearby::analytics { + +struct OperationResultWithMedium { + location::nearby::proto::connections::Medium medium = + location::nearby::proto::connections::UNKNOWN_MEDIUM; + std::optional update_index; + location::nearby::proto::connections::OperationResultCategory + result_category = location::nearby::proto::connections::CATEGORY_UNKNOWN; + location::nearby::proto::connections::OperationResultCode result_code = + location::nearby::proto::connections::DETAIL_UNKNOWN; + std::optional + connection_mode; + + void set_medium(location::nearby::proto::connections::Medium m) { + medium = m; + } + void set_update_index(int i) { update_index = i; } + void set_result_category( + location::nearby::proto::connections::OperationResultCategory c) { + result_category = c; + } + void set_result_code( + location::nearby::proto::connections::OperationResultCode c) { + result_code = c; + } + void set_connection_mode( + location::nearby::proto::connections::ConnectionMode m) { + connection_mode = m; + } +}; + +} // namespace nearby::analytics + +#endif // ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_ diff --git a/connections/implementation/base_endpoint_channel.cc b/connections/implementation/base_endpoint_channel.cc index 16baec65..79ba0de0 100644 --- a/connections/implementation/base_endpoint_channel.cc +++ b/connections/implementation/base_endpoint_channel.cc @@ -40,15 +40,13 @@ #include "internal/platform/mutex_lock.h" #include "internal/platform/output_stream.h" -namespace nearby { -namespace connections { +namespace nearby::connections { namespace { -using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::proto::connections::Medium::BLE; using ::location::nearby::proto::connections::Medium::BLE_L2CAP; -using DisconnectionReason = - ::location::nearby::proto::connections::DisconnectionReason; +using ::nearby::analytics::SafeDisconnectionResult; +using ::location::nearby::proto::connections::DisconnectionReason; Exception WriteInt(OutputStream* writer, std::int32_t value) { return Base64Utils::WriteInt(writer, value); @@ -304,7 +302,7 @@ void BaseEndpointChannel::SetAnalyticsRecorder( void BaseEndpointChannel::Close( location::nearby::proto::connections::DisconnectionReason reason) { - Close(reason, ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + Close(reason, SafeDisconnectionResult::kSafeDisconnection); } void BaseEndpointChannel::Close( @@ -468,5 +466,4 @@ std::unique_ptr BaseEndpointChannel::EncodeMessageForTests( return crypto_context_->EncodeMessageToPeer(data); } -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/base_endpoint_channel.h b/connections/implementation/base_endpoint_channel.h index c426c118..421a8a9f 100644 --- a/connections/implementation/base_endpoint_channel.h +++ b/connections/implementation/base_endpoint_channel.h @@ -31,8 +31,7 @@ #include "internal/platform/mutex.h" #include "internal/platform/output_stream.h" -namespace nearby { -namespace connections { +namespace nearby::connections { class BaseEndpointChannel : public EndpointChannel { public: @@ -56,10 +55,8 @@ class BaseEndpointChannel : public EndpointChannel { void Close() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; void Close(location::nearby::proto::connections::DisconnectionReason reason) override; - void Close( - location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result) override; + void Close(location::nearby::proto::connections::DisconnectionReason reason, + nearby::analytics::SafeDisconnectionResult result) override; bool IsClosed() const ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; std::string GetType() const override; std::string GetServiceId() const override; @@ -171,7 +168,6 @@ class BaseEndpointChannel : public EndpointChannel { std::string endpoint_id_ = ""; }; -} // namespace connections -} // namespace nearby +} // namespace nearby::connections #endif // CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ diff --git a/connections/implementation/base_pcp_handler.cc b/connections/implementation/base_pcp_handler.cc index 59418df5..85a82eae 100644 --- a/connections/implementation/base_pcp_handler.cc +++ b/connections/implementation/base_pcp_handler.cc @@ -36,7 +36,9 @@ #include "connections/advertising_options.h" #include "connections/connection_options.h" #include "connections/discovery_options.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "connections/implementation/bwu_manager.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/connections_authentication_transport.h" @@ -89,6 +91,20 @@ namespace nearby::connections { namespace { +using ::location::nearby::analytics::proto::ConnectionsLog; +using ::location::nearby::connections::ConnectionRequestFrame; +using ::location::nearby::connections::ConnectionResponseFrame; +using ::location::nearby::connections::ConnectionsDevice; +using ::location::nearby::connections::MediumMetadata; +using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::connections::OsInfo; +using ::location::nearby::connections::PresenceDevice; +using ::location::nearby::connections::V1Frame; +using ::location::nearby::proto::connections::OperationResultCode; +using ::location::nearby::proto::connections::WifiDirectAuthType; +using ::nearby::analytics::AnalyticsRecorder; +using ::securegcm::UKey2Handshake; + constexpr int kEndpointCancelAlarmTimeout = 10; std::string AuthenticationStatusToString(nearby::AuthenticationStatus status) { @@ -101,20 +117,30 @@ std::string AuthenticationStatusToString(nearby::AuthenticationStatus status) { return "failure"; } } -} // namespace -using ::location::nearby::analytics::proto::ConnectionsLog; -using ::location::nearby::connections::ConnectionRequestFrame; -using ::location::nearby::connections::ConnectionResponseFrame; -using ::location::nearby::connections::ConnectionsDevice; -using ::location::nearby::connections::MediumMetadata; -using ::location::nearby::connections::OfflineFrame; -using ::location::nearby::connections::OsInfo; -using ::location::nearby::connections::PresenceDevice; -using ::location::nearby::connections::V1Frame; -using ::location::nearby::proto::connections::OperationResultCode; -using ::location::nearby::proto::connections::WifiDirectAuthType; -using ::securegcm::UKey2Handshake; +std::vector +ConvertToCppOperationResultWithMediums( + const std::vector& + proto_results) { + std::vector cpp_results; + cpp_results.reserve(proto_results.size()); + for (const auto& proto_result : proto_results) { + analytics::OperationResultWithMedium cpp_result; + cpp_result.medium = proto_result.medium(); + if (proto_result.has_update_index()) { + cpp_result.update_index = proto_result.update_index(); + } + cpp_result.result_category = proto_result.result_category(); + cpp_result.result_code = proto_result.result_code(); + if (proto_result.has_connection_mode()) { + cpp_result.connection_mode = proto_result.connection_mode(); + } + cpp_results.push_back(cpp_result); + } + return cpp_results; +} + +} // namespace BasePcpHandler::BasePcpHandler(Mediums* mediums, EndpointManager* endpoint_manager, @@ -278,11 +304,11 @@ Status BasePcpHandler::StartAdvertising( // Save the advertising options for local reference in later process // like upgrading bandwidth. advertising_listener_ = info.listener; - client->StartedAdvertising( - service_id, GetStrategy(), info.listener, - absl::MakeSpan(result.mediums), - std::move(result.operation_result_with_mediums), - compatible_advertising_options); + client->StartedAdvertising(service_id, GetStrategy(), info.listener, + absl::MakeSpan(result.mediums), + ConvertToCppOperationResultWithMediums( + result.operation_result_with_mediums), + compatible_advertising_options); client->UpdateLocalEndpointInfo(info.endpoint_info.string_data()); response.Set({Status::kSuccess}); }); @@ -509,11 +535,12 @@ Status BasePcpHandler::StartDiscovery(ClientProxy* client, MutexLock lock(&discovered_endpoint_mutex_); discovered_endpoints_.clear(); } - client->StartedDiscovery( - service_id, GetStrategy(), std::move(listener), - absl::MakeSpan(result.mediums), - std::move(result.operation_result_with_mediums), - stripped_discovery_options); + client->StartedDiscovery(service_id, GetStrategy(), + std::move(listener), + absl::MakeSpan(result.mediums), + ConvertToCppOperationResultWithMediums( + result.operation_result_with_mediums), + stripped_discovery_options); response.Set({Status::kSuccess}); }); return WaitForResult(absl::StrCat("StartDiscovery(", service_id, ")"), @@ -1011,8 +1038,8 @@ Status BasePcpHandler::RequestConnection( client, channel_medium, endpoint_id, channel.get(), /*is_incoming=*/false, /*log_failure=*/true, start_time, {Status::kEndpointIoError}, - client->GetAnalyticsRecorder() - .GetChannelIoErrorResultCodeFromMedium(channel_medium), + AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( + channel_medium), result.get()); return; } @@ -1173,8 +1200,8 @@ Status BasePcpHandler::RequestConnectionV3( client, channel_medium, endpoint_id, channel.get(), /*is_incoming=*/false, /*log_failure=*/true, start_time, {Status::kEndpointIoError}, - client->GetAnalyticsRecorder() - .GetChannelIoErrorResultCodeFromMedium(channel_medium), + AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( + channel_medium), result.get()); return; } @@ -2032,8 +2059,7 @@ Exception BasePcpHandler::OnIncomingConnection( /*is_incoming=*/true, /*log_failure=*/wrapped_frame.exception() != Exception::kNoData, start_time, {Status::kError}, - client->GetAnalyticsRecorder().GetChannelIoErrorResultCodeFromMedium( - medium), + AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium(medium), nullptr); } return wrapped_frame.GetException(); @@ -2584,7 +2610,7 @@ void BasePcpHandler::LogConnectionAttemptFailure( connections_attempt_metadata_params; if (endpoint_channel != nullptr) { connections_attempt_metadata_params = - client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( + AnalyticsRecorder::BuildConnectionAttemptMetadataParams( endpoint_channel->GetTechnology(), endpoint_channel->GetBand(), endpoint_channel->GetFrequency(), endpoint_channel->GetTryCount()); connections_attempt_metadata_params->operation_result_code = @@ -2610,12 +2636,11 @@ void BasePcpHandler::LogConnectionAttemptSuccess( connections_attempt_metadata_params; if (pending_connection_info.channel != nullptr) { connections_attempt_metadata_params = - pending_connection_info.client->GetAnalyticsRecorder() - .BuildConnectionAttemptMetadataParams( - pending_connection_info.channel->GetTechnology(), - pending_connection_info.channel->GetBand(), - pending_connection_info.channel->GetFrequency(), - pending_connection_info.channel->GetTryCount()); + AnalyticsRecorder::BuildConnectionAttemptMetadataParams( + pending_connection_info.channel->GetTechnology(), + pending_connection_info.channel->GetBand(), + pending_connection_info.channel->GetFrequency(), + pending_connection_info.channel->GetTryCount()); connections_attempt_metadata_params->operation_result_code = OperationResultCode::DETAIL_SUCCESS; } else { diff --git a/connections/implementation/bwu_manager.cc b/connections/implementation/bwu_manager.cc index 48a70718..76b93cc6 100644 --- a/connections/implementation/bwu_manager.cc +++ b/connections/implementation/bwu_manager.cc @@ -25,6 +25,7 @@ #include "absl/functional/bind_front.h" #include "absl/strings/str_cat.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" #include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" @@ -61,6 +62,8 @@ using ::location::nearby::proto::connections::ConnectionAttemptResult; using ::location::nearby::proto::connections::ConnectionAttemptType; using ::location::nearby::proto::connections::DisconnectionReason; using ::location::nearby::proto::connections::OperationResultCode; +using ::nearby::analytics::AnalyticsRecorder; + } // namespace BwuManager::BwuManager( @@ -663,7 +666,7 @@ void BwuManager::OnIncomingConnection( connections_attempt_metadata_params; if (channel != nullptr) { connections_attempt_metadata_params = - client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( + AnalyticsRecorder::BuildConnectionAttemptMetadataParams( channel->GetTechnology(), channel->GetBand(), channel->GetFrequency(), channel->GetTryCount()); connections_attempt_metadata_params->operation_result_code = @@ -874,7 +877,7 @@ void BwuManager::ProcessBwuPathAvailableEvent( if (channel != nullptr) { std::unique_ptr connections_attempt_metadata_params = - client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( + AnalyticsRecorder::BuildConnectionAttemptMetadataParams( channel->GetTechnology(), channel->GetBand(), channel->GetFrequency(), channel->GetTryCount()); connections_attempt_metadata_params->operation_result_code = diff --git a/connections/implementation/bwu_manager_test.cc b/connections/implementation/bwu_manager_test.cc index 6a6495c5..dd858901 100644 --- a/connections/implementation/bwu_manager_test.cc +++ b/connections/implementation/bwu_manager_test.cc @@ -22,6 +22,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "connections/connection_options.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel.h" @@ -41,19 +42,17 @@ #include "internal/platform/exception.h" #include "internal/platform/feature_flags.h" #include "internal/platform/service_address.h" -#include "internal/proto/analytics/connections_log.pb.h" #include "proto/connections_enums.pb.h" -namespace nearby { -namespace connections { +namespace nearby::connections { namespace { -using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame; using ::location::nearby::connections::MediumRole; using ::location::nearby::connections::OfflineFrame; using ::location::nearby::connections::OsInfo; using ::location::nearby::connections::V1Frame; using ::location::nearby::proto::connections::DisconnectionReason; +using ::nearby::analytics::SafeDisconnectionResult; constexpr absl::string_view kServiceIdA = "ServiceA"; constexpr absl::string_view kServiceIdB = "ServiceB"; @@ -148,7 +147,7 @@ class BwuManagerTest : public ::testing::Test { void UnRegisterChannelForEndpoint(absl::string_view endpoint_id) { ecm_.UnregisterChannelForEndpoint( std::string(endpoint_id), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); } // Upgrade from |initial_medium| to |upgrade_medium|, close down the BLUETOOTH @@ -232,9 +231,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) { bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId1), Medium::WIFI_LAN); EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId1))); - ecm.UnregisterChannelForEndpoint( - std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + ecm.UnregisterChannelForEndpoint(std::string(kEndpointId1), + DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); auto channel2 = std::make_unique( Medium::BLUETOOTH, std::string(kServiceIdA)); @@ -243,9 +242,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) { bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId2), Medium::WIFI_HOTSPOT); EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId2))); - ecm.UnregisterChannelForEndpoint( - std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + ecm.UnregisterChannelForEndpoint(std::string(kEndpointId2), + DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); auto channel3 = std::make_unique( Medium::BLUETOOTH, std::string(kServiceIdA)); @@ -254,9 +253,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) { bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId3), Medium::WIFI_DIRECT); EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId3))); - ecm.UnregisterChannelForEndpoint( - std::string(kEndpointId3), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + ecm.UnregisterChannelForEndpoint(std::string(kEndpointId3), + DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); auto channel4 = std::make_unique( Medium::WEB_RTC, std::string(kServiceIdA)); @@ -265,9 +264,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) { bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId4), Medium::BLUETOOTH); EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId4))); - ecm.UnregisterChannelForEndpoint( - std::string(kEndpointId4), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + ecm.UnregisterChannelForEndpoint(std::string(kEndpointId4), + DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); bwu_manager->Shutdown(); } @@ -307,9 +306,9 @@ TEST(BwuManagerBaseTest, InitiateBwu_NeedToSwitchRole_Success) { Medium::WIFI_HOTSPOT); EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId1))); - ecm.UnregisterChannelForEndpoint( - std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + ecm.UnregisterChannelForEndpoint(std::string(kEndpointId1), + DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); bwu_manager->Shutdown(); NearbyFlags::GetInstance().OverrideBoolFlagValue( config_package_nearby::nearby_connections_feature:: @@ -500,7 +499,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id, std::string(kEndpointId1), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -514,7 +513,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id, std::string(kEndpointId2), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -548,7 +547,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id, std::string(kEndpointId1), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -568,7 +567,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id, std::string(kEndpointId2), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -605,7 +604,7 @@ TEST_F(BwuManagerTest, EXPECT_EQ(2u, ecm_.GetConnectedEndpointsCount()); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); EXPECT_EQ(1u, ecm_.GetConnectedEndpointsCount()); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_A, std::string(kEndpointId1), latch, @@ -625,7 +624,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); EXPECT_EQ(0u, ecm_.GetConnectedEndpointsCount()); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_B, std::string(kEndpointId2), latch, @@ -659,7 +658,7 @@ TEST_F(BwuManagerTest, EXPECT_EQ(2u, ecm_.GetConnectedEndpointsCount()); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); EXPECT_EQ(1u, ecm_.GetConnectedEndpointsCount()); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_A, std::string(kEndpointId1), latch, @@ -679,7 +678,7 @@ TEST_F(BwuManagerTest, CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); EXPECT_EQ(0u, ecm_.GetConnectedEndpointsCount()); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_B, std::string(kEndpointId2), latch, @@ -735,7 +734,7 @@ TEST_F( CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_A, std::string(kEndpointId1), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -760,7 +759,7 @@ TEST_F( CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_A, std::string(kEndpointId2), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -781,7 +780,7 @@ TEST_F( CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId3), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_B, std::string(kEndpointId3), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -802,7 +801,7 @@ TEST_F( CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId4), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_B, std::string(kEndpointId4), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -825,7 +824,7 @@ TEST_F( CountDownLatch latch(1); ecm_.UnregisterChannelForEndpoint( std::string(kEndpointId5), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION); + SafeDisconnectionResult::kUnsafeDisconnection); bwu_manager_->OnEndpointDisconnect( &client_, upgrade_service_id_B, std::string(kEndpointId5), latch, DisconnectionReason::LOCAL_DISCONNECTION); @@ -1094,5 +1093,4 @@ INSTANTIATE_TEST_SUITE_P(BwuManagerTestParam, BwuManagerTestParam, testing::Bool()); } // namespace -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/client_proxy.cc b/connections/implementation/client_proxy.cc index f35d9f6d..e4737d0f 100644 --- a/connections/implementation/client_proxy.cc +++ b/connections/implementation/client_proxy.cc @@ -38,7 +38,9 @@ #include "connections/discovery_options.h" #include "connections/implementation/analytics/advertising_metadata_params.h" #include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/analytics_recorder_impl.h" #include "connections/implementation/analytics/discovery_metadata_params.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "connections/implementation/mediums/advertisements/dct_advertisement.h" #include "connections/listeners.h" @@ -79,9 +81,9 @@ namespace nearby::connections { namespace { -using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::connections::MediumRole; using ::location::nearby::connections::OsInfo; +using ::nearby::analytics::AnalyticsRecorder; constexpr char kEndpointIdChars[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', @@ -111,7 +113,7 @@ ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger) is_dct_enabled_ = NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableDct); analytics_recorder_ = - std::make_unique(event_logger); + std::make_unique(event_logger); error_code_recorder_ = std::make_unique( [this](const ErrorCodeParams& params) { analytics_recorder_->OnErrorCode(params); @@ -262,7 +264,7 @@ void ClientProxy::StartedAdvertising( const std::string& service_id, Strategy strategy, const ConnectionListener& listener, absl::Span mediums, - const std::vector& + const std::vector& operation_result_with_mediums, const AdvertisingOptions& advertising_options) { MutexLock lock(&mutex_); @@ -283,9 +285,9 @@ void ClientProxy::StartedAdvertising( mediums.begin(), mediums.end()); std::unique_ptr advertising_metadata_params; advertising_metadata_params = - GetAnalyticsRecorder().BuildAdvertisingMetadataParams(); + AnalyticsRecorder::BuildAdvertisingMetadataParams(); advertising_metadata_params->operation_result_with_mediums = - std::move(operation_result_with_mediums); + operation_result_with_mediums; analytics_recorder_->OnStartAdvertising(strategy, medium_vector, advertising_metadata_params.get()); } @@ -401,7 +403,7 @@ void ClientProxy::StartedDiscovery( const std::string& service_id, Strategy strategy, DiscoveryListener listener, absl::Span mediums, - const std::vector& + const std::vector& operation_result_with_mediums, const DiscoveryOptions& discovery_options) { MutexLock lock(&mutex_); @@ -411,10 +413,9 @@ void ClientProxy::StartedDiscovery( const std::vector medium_vector( mediums.begin(), mediums.end()); std::unique_ptr discovery_metadata_params; - discovery_metadata_params = - GetAnalyticsRecorder().BuildDiscoveryMetadataParams(); + discovery_metadata_params = AnalyticsRecorder::BuildDiscoveryMetadataParams(); discovery_metadata_params->operation_result_with_mediums = - std::move(operation_result_with_mediums); + operation_result_with_mediums; analytics_recorder_->OnStartDiscovery(strategy, medium_vector, discovery_metadata_params.get()); } diff --git a/connections/implementation/client_proxy.h b/connections/implementation/client_proxy.h index 685765a8..e4929736 100644 --- a/connections/implementation/client_proxy.h +++ b/connections/implementation/client_proxy.h @@ -32,6 +32,7 @@ #include "connections/connection_options.h" #include "connections/discovery_options.h" #include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/operation_result_with_medium.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "connections/listeners.h" #include "connections/medium_selector.h" @@ -54,7 +55,6 @@ #include "internal/platform/mutex.h" #include "internal/platform/os_name.h" #include "internal/platform/scheduled_executor.h" -#include "internal/proto/analytics/connections_log.pb.h" namespace nearby::connections { @@ -109,8 +109,7 @@ class ClientProxy final { const std::string& service_id, Strategy strategy, const ConnectionListener& connection_lifecycle_listener, absl::Span mediums, - const std::vector& + const std::vector& operation_result_with_medium, const AdvertisingOptions& advertising_options = AdvertisingOptions{}); // Marks this client as not advertising. @@ -134,8 +133,7 @@ class ClientProxy final { const std::string& service_id, Strategy strategy, DiscoveryListener discovery_listener, absl::Span mediums, - const std::vector& + const std::vector& operation_result_with_medium, const DiscoveryOptions& discovery_options = DiscoveryOptions{}); // Marks this client as not discovering at all. diff --git a/connections/implementation/encryption_runner_test.cc b/connections/implementation/encryption_runner_test.cc index ee9bbc1d..743c1658 100644 --- a/connections/implementation/encryption_runner_test.cc +++ b/connections/implementation/encryption_runner_test.cc @@ -35,8 +35,7 @@ #include "proto/connections_enums.pb.h" #include "third_party/ukey2/src/main/cpp/include/securegcm/ukey2_handshake.h" -namespace nearby { -namespace connections { +namespace nearby::connections { namespace { using ::location::nearby::proto::connections::Medium; @@ -65,10 +64,8 @@ class FakeEndpointChannel : public EndpointChannel { override { Close(); } - void Close( - location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result) override { + void Close(location::nearby::proto::connections::DisconnectionReason reason, + nearby::analytics::SafeDisconnectionResult result) override { Close(); } bool IsClosed() const override { return false; } @@ -410,5 +407,4 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage3) { } } // namespace -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/endpoint_channel.h b/connections/implementation/endpoint_channel.h index fc0d87cf..1b286475 100644 --- a/connections/implementation/endpoint_channel.h +++ b/connections/implementation/endpoint_channel.h @@ -26,8 +26,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/exception.h" -namespace nearby { -namespace connections { +namespace nearby::connections { class EndpointChannel { public: @@ -51,8 +50,7 @@ class EndpointChannel { // and safe disconnection result. virtual void Close( location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result) = 0; + nearby::analytics::SafeDisconnectionResult result) = 0; // True if the EndpointChannel is currently closed. virtual bool IsClosed() const = 0; @@ -141,7 +139,6 @@ inline bool operator!=(const EndpointChannel& lhs, const EndpointChannel& rhs) { return !(lhs == rhs); } -} // namespace connections -} // namespace nearby +} // namespace nearby::connections #endif // CORE_INTERNAL_ENDPOINT_CHANNEL_H_ diff --git a/connections/implementation/endpoint_channel_manager.cc b/connections/implementation/endpoint_channel_manager.cc index c6af41d4..ab2af35d 100644 --- a/connections/implementation/endpoint_channel_manager.cc +++ b/connections/implementation/endpoint_channel_manager.cc @@ -29,10 +29,7 @@ #include "internal/platform/mutex.h" #include "internal/platform/mutex_lock.h" -namespace nearby { -namespace connections { -using ::location::nearby::analytics::proto::ConnectionsLog; - +namespace nearby::connections { namespace { const absl::Duration kDataTransferDelay = absl::Milliseconds(500); } @@ -183,7 +180,7 @@ void EndpointChannelManager::ChannelState::DestroyAll() { for (auto& item : endpoints_) { RemoveEndpoint(item.first, DisconnectionReason::SHUTDOWN, /* safe_to_disconnect_enabled */ false, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); } endpoints_.clear(); } @@ -365,5 +362,4 @@ bool EndpointChannelManager::UnregisterChannelForEndpoint( return true; } -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/endpoint_channel_manager.h b/connections/implementation/endpoint_channel_manager.h index 19183ee0..47878023 100644 --- a/connections/implementation/endpoint_channel_manager.h +++ b/connections/implementation/endpoint_channel_manager.h @@ -21,18 +21,16 @@ #include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel.h" #include "internal/platform/mutex.h" -#include "internal/proto/analytics/connections_log.pb.h" #include "proto/connections_enums.pb.h" -namespace nearby { -namespace connections { +namespace nearby::connections { using DisconnectionReason = ::location::nearby::proto::connections::DisconnectionReason; -using SafeDisconnectionResult = ::location::nearby::analytics::proto:: - ConnectionsLog::EstablishedConnection::SafeDisconnectionResult; +using SafeDisconnectionResult = nearby::analytics::SafeDisconnectionResult; // NOTE(std::string): // All the strings in internal class public interfaces should be exchanged as @@ -215,7 +213,6 @@ class EndpointChannelManager final { ChannelState channel_state_; }; -} // namespace connections -} // namespace nearby +} // namespace nearby::connections #endif // CORE_INTERNAL_ENDPOINT_CHANNEL_MANAGER_H_ diff --git a/connections/implementation/endpoint_channel_manager_test.cc b/connections/implementation/endpoint_channel_manager_test.cc index d73b746b..0bdbb6d1 100644 --- a/connections/implementation/endpoint_channel_manager_test.cc +++ b/connections/implementation/endpoint_channel_manager_test.cc @@ -27,6 +27,7 @@ #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/base_endpoint_channel.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/encryption_runner.h" @@ -39,16 +40,14 @@ #include "internal/platform/multi_thread_executor.h" #include "internal/platform/output_stream.h" #include "internal/platform/pipe.h" -#include "internal/proto/analytics/connections_log.pb.h" #include "proto/connections_enums.pb.h" -namespace nearby { -namespace connections { +namespace nearby::connections { namespace { -using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::proto::connections::DisconnectionReason; using ::location::nearby::proto::connections::Medium; +using ::nearby::analytics::SafeDisconnectionResult; using EncryptionContext = BaseEndpointChannel::EncryptionContext; constexpr size_t kChunkSize = 64 * 1024; @@ -243,10 +242,10 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) { channel_b_raw->Close(DisconnectionReason::REMOTE_DISCONNECTION); ecm_a.UnregisterChannelForEndpoint( std::string(kEndpointId), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); ecm_b.UnregisterChannelForEndpoint( std::string(kEndpointId), DisconnectionReason::REMOTE_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); } TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) { @@ -311,12 +310,11 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) { channel_b_raw->Close(DisconnectionReason::REMOTE_DISCONNECTION); ecm_a.UnregisterChannelForEndpoint( std::string(kEndpointId), DisconnectionReason::LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); ecm_b.UnregisterChannelForEndpoint( std::string(kEndpointId), DisconnectionReason::REMOTE_DISCONNECTION, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); } } // namespace -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/endpoint_manager.cc b/connections/implementation/endpoint_manager.cc index 5070d390..31b4454b 100644 --- a/connections/implementation/endpoint_manager.cc +++ b/connections/implementation/endpoint_manager.cc @@ -24,6 +24,7 @@ #include "absl/functional/any_invocable.h" #include "absl/time/time.h" #include "connections/connection_options.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/endpoint_channel_manager.h" @@ -42,19 +43,17 @@ #include "internal/platform/mutex_lock.h" #include "internal/platform/runnable.h" #include "internal/platform/single_thread_executor.h" -#include "internal/proto/analytics/connections_log.pb.h" #include "proto/connections_enums.pb.h" -namespace nearby { -namespace connections { +namespace nearby::connections { namespace { -using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::connections::KeepAliveFrame; using ::location::nearby::connections::OfflineFrame; using ::location::nearby::connections::PayloadTransferFrame; using ::location::nearby::connections::V1Frame; using ::location::nearby::proto::connections::DisconnectionReason; +using ::nearby::analytics::SafeDisconnectionResult; // We set this to 11s to provide sufficient time for an in-progress WebRTC // bandwidth upgrade to resolve. This is chosen to be slightly longer than the @@ -743,7 +742,7 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client, << ", reason: " << reason; SafeDisconnectionResult safe_disconnect_result = - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION; + SafeDisconnectionResult::kSafeDisconnection; // Grab the service ID before we destroy the channel. EndpointChannel* channel = @@ -756,11 +755,13 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client, bool is_safe_disconnection = ApplySafeToDisconnect(endpoint_id, channel, reason); safe_disconnect_result = - is_safe_disconnection - ? ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION - : ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION; + is_safe_disconnection ? SafeDisconnectionResult::kSafeDisconnection + : SafeDisconnectionResult::kUnsafeDisconnection; LOG(INFO) << "[safe-to-disconnect] safe_disconnect_result:" - << (safe_disconnect_result ? "true" : "false"); + << (safe_disconnect_result == + SafeDisconnectionResult::kSafeDisconnection + ? "true" + : "false"); } } @@ -953,7 +954,7 @@ EndpointManager::EndpointState::~EndpointState() { VLOG(1) << "EndpointState destructor " << endpoint_id_; channel_manager_->UnregisterChannelForEndpoint( endpoint_id_, DisconnectionReason::SHUTDOWN, - ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); + SafeDisconnectionResult::kSafeDisconnection); } // Make sure the KeepAlive thread isn't blocking shutdown. @@ -982,5 +983,4 @@ void EndpointManager::RunOnEndpointManagerThread(const std::string& name, serial_executor_->Execute(name, std::move(runnable)); } -} // namespace connections -} // namespace nearby +} // namespace nearby::connections diff --git a/connections/implementation/fake_endpoint_channel.h b/connections/implementation/fake_endpoint_channel.h index cb03659f..01bb92fe 100644 --- a/connections/implementation/fake_endpoint_channel.h +++ b/connections/implementation/fake_endpoint_channel.h @@ -27,8 +27,7 @@ #include "internal/platform/exception.h" #include "internal/platform/implementation/system_clock.h" -namespace nearby { -namespace connections { +namespace nearby::connections { // An endpoint channel implementation used for testing. The read and write // output can be set. @@ -56,10 +55,8 @@ class FakeEndpointChannel : public EndpointChannel { is_closed_ = true; disconnection_reason_ = reason; } - void Close( - location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result) override { + void Close(location::nearby::proto::connections::DisconnectionReason reason, + nearby::analytics::SafeDisconnectionResult result) override { Close(reason); } bool IsClosed() const override { return is_closed_; } @@ -119,7 +116,6 @@ class FakeEndpointChannel : public EndpointChannel { mutable uint32_t next_keep_alive_seq_no_ = 0; }; -} // namespace connections -} // namespace nearby +} // namespace nearby::connections #endif // NEARBY_CONNECTIONS_IMPLEMENTATION_FAKE_ENDPOINT_CHANNEL_H_ diff --git a/connections/implementation/mock_endpoint_channel.h b/connections/implementation/mock_endpoint_channel.h index 87f51995..14ea499e 100644 --- a/connections/implementation/mock_endpoint_channel.h +++ b/connections/implementation/mock_endpoint_channel.h @@ -40,8 +40,7 @@ class MockEndpointChannel : public EndpointChannel { (override)); MOCK_METHOD(void, Close, (location::nearby::proto::connections::DisconnectionReason reason, - location::nearby::analytics::proto::ConnectionsLog:: - EstablishedConnection::SafeDisconnectionResult result), + nearby::analytics::SafeDisconnectionResult result), (override)); MOCK_METHOD(bool, IsClosed, (), (const, override)); MOCK_METHOD(std::string, GetType, (), (const, override)); diff --git a/connections/implementation/payload_manager.cc b/connections/implementation/payload_manager.cc index f534a2ed..6529b211 100644 --- a/connections/implementation/payload_manager.cc +++ b/connections/implementation/payload_manager.cc @@ -29,6 +29,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/analytics_recorder.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" @@ -63,7 +64,7 @@ using ::location::nearby::connections::V1Frame; using ::location::nearby::proto::connections::Medium; using ::location::nearby::proto::connections::OperationResultCode; using ::location::nearby::proto::connections::PayloadStatus; -using PayloadDirection = ::nearby::connections::PayloadDirection; +using ::nearby::analytics::AnalyticsRecorder; constexpr absl::Duration kMinTransferUpdateInterval = absl::Milliseconds(50); } // namespace @@ -620,9 +621,8 @@ void PayloadManager::OnEndpointDisconnect(ClientProxy* client, default: payload_status = PayloadStatus::ENDPOINT_IO_ERROR; operation_result_code = - client->GetAnalyticsRecorder() - .GetChannelIoErrorResultCodeFromMedium( - client->GetConnectedMedium(endpoint_id)); + AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( + client->GetConnectedMedium(endpoint_id)); break; } @@ -839,9 +839,8 @@ void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( endpoint_id, payload_header.id(), status, (operation_result_code == OperationResultCode::DETAIL_UNKNOWN && status == PayloadStatus::ENDPOINT_IO_ERROR) - ? client->GetAnalyticsRecorder() - .GetChannelIoErrorResultCodeFromMedium( - client->GetConnectedMedium(endpoint_id)) + ? AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( + client->GetConnectedMedium(endpoint_id)) : operation_result_code); }