From 6bd7d5f84f76b495d0eb7152a799f75eb894d16a Mon Sep 17 00:00:00 2001 From: Edwin Wu Date: Fri, 22 Nov 2024 00:00:57 -0800 Subject: [PATCH] analytics: Add exact OperationResultCode for Wifi_Lan - Connect/AttemptConnect PiperOrigin-RevId: 699063238 --- connections/implementation/analytics/BUILD | 3 + .../analytics/advertising_metadata_params.h | 36 + .../analytics/analytics_recorder.cc | 563 ++++++-- .../analytics/analytics_recorder.h | 160 ++- .../analytics/analytics_recorder_test.cc | 1219 +++++++++++------ .../connection_attempt_metadata_params.h | 3 + .../analytics/discovery_metadata_params.h | 36 + .../implementation/base_bwu_handler_test.cc | 22 +- .../implementation/base_pcp_handler.cc | 77 +- connections/implementation/base_pcp_handler.h | 32 +- .../implementation/bluetooth_bwu_handler.cc | 37 +- .../implementation/bluetooth_bwu_handler.h | 19 +- .../implementation/bluetooth_bwu_test.cc | 13 +- connections/implementation/bwu_handler.h | 17 +- connections/implementation/bwu_manager.cc | 211 +-- connections/implementation/bwu_manager.h | 26 +- connections/implementation/client_proxy.cc | 43 +- connections/implementation/client_proxy.h | 11 + .../implementation/client_proxy_test.cc | 12 +- .../implementation/endpoint_manager.cc | 5 +- connections/implementation/fake_bwu_handler.h | 12 +- .../internal_payload_factory.cc | 40 +- .../implementation/internal_payload_factory.h | 9 +- .../internal_payload_factory_test.cc | 48 +- connections/implementation/mediums/ble.cc | 34 +- connections/implementation/mediums/ble.h | 12 +- .../implementation/mediums/ble_test.cc | 15 +- connections/implementation/mediums/ble_v2.cc | 95 +- connections/implementation/mediums/ble_v2.h | 25 +- .../implementation/mediums/ble_v2_test.cc | 18 +- .../mediums/bluetooth_classic.cc | 107 +- .../mediums/bluetooth_classic.h | 23 +- .../mediums/bluetooth_classic_test.cc | 58 +- .../implementation/mediums/wifi_lan.cc | 94 +- connections/implementation/mediums/wifi_lan.h | 31 +- .../implementation/mediums/wifi_lan_test.cc | 61 +- .../implementation/p2p_cluster_pcp_handler.cc | 1126 +++++++++------ .../implementation/p2p_cluster_pcp_handler.h | 30 +- connections/implementation/payload_manager.cc | 289 ++-- connections/implementation/payload_manager.h | 145 +- .../implementation/payload_manager_test.cc | 4 +- .../implementation/reconnect_manager.cc | 6 +- .../service_controller_router_test.cc | 6 +- .../implementation/webrtc_bwu_handler.cc | 13 +- .../implementation/webrtc_bwu_handler.h | 15 +- .../implementation/webrtc_bwu_handler_stub.cc | 9 +- .../implementation/webrtc_bwu_handler_stub.h | 14 +- .../implementation/wifi_direct_bwu_handler.cc | 19 +- .../implementation/wifi_direct_bwu_handler.h | 21 +- .../implementation/wifi_direct_bwu_test.cc | 21 +- .../wifi_hotspot_bwu_handler.cc | 18 +- .../implementation/wifi_hotspot_bwu_handler.h | 22 +- .../implementation/wifi_hotspot_bwu_test.cc | 22 +- .../implementation/wifi_lan_bwu_handler.cc | 39 +- .../implementation/wifi_lan_bwu_handler.h | 22 +- 55 files changed, 3452 insertions(+), 1616 deletions(-) create mode 100644 connections/implementation/analytics/advertising_metadata_params.h create mode 100644 connections/implementation/analytics/discovery_metadata_params.h diff --git a/connections/implementation/analytics/BUILD b/connections/implementation/analytics/BUILD index 2f9435e956..c2dd6e1546 100644 --- a/connections/implementation/analytics/BUILD +++ b/connections/implementation/analytics/BUILD @@ -20,8 +20,10 @@ cc_library( "throughput_recorder.cc", ], hdrs = [ + "advertising_metadata_params.h", "analytics_recorder.h", "connection_attempt_metadata_params.h", + "discovery_metadata_params.h", "packet_meta_data.h", "throughput_recorder.h", ], @@ -57,6 +59,7 @@ cc_test( shard_count = 16, deps = [ ":analytics", + "//connections:core_types", "//internal/analytics:mock_event_logger", "//internal/platform:base", "//internal/platform:error_code_recorder", diff --git a/connections/implementation/analytics/advertising_metadata_params.h b/connections/implementation/analytics/advertising_metadata_params.h new file mode 100644 index 0000000000..2b3b3372cb --- /dev/null +++ b/connections/implementation/analytics/advertising_metadata_params.h @@ -0,0 +1,36 @@ +// Copyright 2024 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_ADVERTISING_METADATA_PARAMS_H_ +#define ANALYTICS_ADVERTISING_METADATA_PARAMS_H_ + +#include + +#include "internal/proto/analytics/connections_log.pb.h" + +namespace nearby { + +// A struct to construct AdvertisingMetadata for the analytics recorder. +struct AdvertisingMetadataParams { + bool is_extended_advertisement_supported = false; + int connected_ap_frequency = 0; + bool is_nfc_available = false; + std::vector + operation_result_with_mediums = {}; +}; + +} // namespace nearby + +#endif // ANALYTICS_ADVERTISING_METADATA_PARAMS_H_ diff --git a/connections/implementation/analytics/analytics_recorder.cc b/connections/implementation/analytics/analytics_recorder.cc index daa7bc213e..fa138441aa 100644 --- a/connections/implementation/analytics/analytics_recorder.cc +++ b/connections/implementation/analytics/analytics_recorder.cc @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,9 @@ #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" @@ -48,7 +49,6 @@ namespace { const char kVersion[] = "v1.0.0"; constexpr absl::string_view kOnStartClientSession = "OnStartClientSession"; const absl::Duration kConnectionTokenMaxLife = absl::Hours(24); -} // namespace using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::proto::connections::ACCEPTED; @@ -76,6 +76,8 @@ 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; @@ -89,6 +91,8 @@ 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; @@ -103,6 +107,57 @@ using ::nearby::analytics::EventLogger; using SafeDisconnectionResult = ::location::nearby::analytics::proto:: ConnectionsLog::EstablishedConnection::SafeDisconnectionResult; +// TODO(edwinwu): Add ifttt in Android counterpart. +OperationResultCategory ConvertToOperationResultCateory( + OperationResultCode result_code) { + if (result_code == OperationResultCode::DETAIL_SUCCESS) { + return OperationResultCategory::CATEGORY_SUCCESS; + } + // Section of CATEGORY_NEARBY_ERROR, starting from 4500 + 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) { NEARBY_LOGS(INFO) << "Start AnalyticsRecorder ctor event_logger_=" @@ -110,6 +165,15 @@ AnalyticsRecorder::AnalyticsRecorder(EventLogger *event_logger) LogStartSession(); } +AnalyticsRecorder::AnalyticsRecorder(EventLogger *event_logger, + bool no_record_time_millis) + : event_logger_(event_logger), + no_record_time_millis_(no_record_time_millis) { + NEARBY_LOGS(INFO) << "Start AnalyticsRecorder ctor event_logger_=" + << event_logger_; + LogStartSession(); +} + AnalyticsRecorder::~AnalyticsRecorder() { serial_executor_.Shutdown(); MutexLock lock(&mutex_); @@ -142,10 +206,20 @@ void AnalyticsRecorder::ResetClientSessionLoggingResoucesLocked() { current_discovery_phase_ = nullptr; } +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, - bool is_extended_advertisement_supported, int connected_ap_frequency, - bool is_nfc_available) { + AdvertisingMetadataParams *advertising_metadata_params) { MutexLock lock(&mutex_); if (!CanRecordAnalyticsLocked("OnStartAdvertising")) { return; @@ -165,12 +239,23 @@ void AnalyticsRecorder::OnStartAdvertising( 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( - is_extended_advertisement_supported); - advertising_metadata->set_connected_ap_frequency(connected_ap_frequency); - advertising_metadata->set_supports_nfc_technology(is_nfc_available); + 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() { @@ -178,13 +263,25 @@ void AnalyticsRecorder::OnStopAdvertising() { if (!CanRecordAnalyticsLocked("OnStopAdvertising")) { return; } - RecordAdvertisingPhaseDurationLocked(); + 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, - bool is_extended_advertisement_supported, int connected_ap_frequency, - bool is_nfc_available) { + DiscoveryMetadataParams *discovery_metadata_params) { MutexLock lock(&mutex_); if (!CanRecordAnalyticsLocked("OnStartDiscovery")) { return; @@ -204,12 +301,23 @@ void AnalyticsRecorder::OnStartDiscovery( 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( - is_extended_advertisement_supported); - discovery_metadata->set_connected_ap_frequency(connected_ap_frequency); - discovery_metadata->set_supports_nfc_technology(is_nfc_available); + 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() { @@ -217,7 +325,19 @@ void AnalyticsRecorder::OnStopDiscovery() { if (!CanRecordAnalyticsLocked("OnStopDiscovery")) { return; } - RecordDiscoveryPhaseDurationLocked(); + 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( @@ -237,7 +357,8 @@ void AnalyticsRecorder::OnStoppedIncomingConnectionListening() { if (!CanRecordAnalyticsLocked("OnStoppedIncomingConnectionListening")) { return; } - RecordAdvertisingPhaseDurationLocked(); + RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); + // RecordAdvertisingPhaseDurationLocked(); } void AnalyticsRecorder::OnEndpointFound(Medium medium) { @@ -253,8 +374,10 @@ void AnalyticsRecorder::OnEndpointFound(Medium medium) { 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_)); + if (!no_record_time_millis_) { + discovered_endpoint->set_latency_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_discovery_phase_time_)); + } } void AnalyticsRecorder::OnRequestConnection( @@ -279,9 +402,11 @@ void AnalyticsRecorder::OnConnectionRequestReceived( 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_)); + if (!no_record_time_millis_) { + 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)}); } @@ -295,9 +420,11 @@ void AnalyticsRecorder::OnConnectionRequestSent( 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_)); + if (!no_record_time_millis_) { + 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)}); } @@ -351,19 +478,34 @@ void AnalyticsRecorder::OnIncomingConnectionAttempt( "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)); + if (!no_record_time_millis_) { + 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); - ConnectionAttemptMetadataParams default_params = {}; - if (connection_attempt_metadata_params == nullptr) { - connection_attempt_metadata_params = &default_params; - } auto *connection_attempt_metadata = connection_attempt->mutable_connection_attempt_metadata(); connection_attempt_metadata->set_technology( @@ -390,6 +532,15 @@ void AnalyticsRecorder::OnIncomingConnectionAttempt( 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(ConvertToOperationResultCateory( + connection_attempt_metadata_params->operation_result_code)); + connection_attempt->set_allocated_operation_result( + operation_result_proto.release()); } void AnalyticsRecorder::OnOutgoingConnectionAttempt( @@ -406,19 +557,43 @@ void AnalyticsRecorder::OnOutgoingConnectionAttempt( "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)); + if (!no_record_time_millis_) { + 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); - ConnectionAttemptMetadataParams default_params = {}; - if (connection_attempt_metadata_params == nullptr) { - connection_attempt_metadata_params = &default_params; - } auto *connection_attempt_metadata = connection_attempt->mutable_connection_attempt_metadata(); connection_attempt_metadata->set_technology( @@ -446,6 +621,15 @@ void AnalyticsRecorder::OnOutgoingConnectionAttempt( 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(ConvertToOperationResultCateory( + 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()) { @@ -475,8 +659,8 @@ void AnalyticsRecorder::OnConnectionEstablished( logical_connection->PhysicalConnectionEstablished(medium, connection_token); } else { active_connections_.insert( - {endpoint_id, - std::make_unique(medium, connection_token)}); + {endpoint_id, std::make_unique( + medium, connection_token, no_record_time_millis_)}); } } @@ -553,9 +737,9 @@ void AnalyticsRecorder::OnPayloadChunkReceived(const std::string &endpoint_id, logical_connection->ChunkReceived(payload_id, chunk_size_bytes); } -void AnalyticsRecorder::OnIncomingPayloadDone(const std::string &endpoint_id, - std::int64_t payload_id, - PayloadStatus status) { +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; @@ -565,7 +749,8 @@ void AnalyticsRecorder::OnIncomingPayloadDone(const std::string &endpoint_id, return; } const std::unique_ptr &logical_connection = it->second; - logical_connection->IncomingPayloadDone(payload_id, status); + logical_connection->IncomingPayloadDone(payload_id, status, + operation_result_code); } void AnalyticsRecorder::OnOutgoingPayloadStarted( @@ -601,9 +786,9 @@ void AnalyticsRecorder::OnPayloadChunkSent(const std::string &endpoint_id, logical_connection->ChunkSent(payload_id, chunk_size_bytes); } -void AnalyticsRecorder::OnOutgoingPayloadDone(const std::string &endpoint_id, - std::int64_t payload_id, - PayloadStatus status) { +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; @@ -612,8 +797,10 @@ void AnalyticsRecorder::OnOutgoingPayloadDone(const std::string &endpoint_id, if (it == active_connections_.end()) { return; } + const std::unique_ptr &logical_connection = it->second; - logical_connection->OutgoingPayloadDone(payload_id, status); + logical_connection->OutgoingPayloadDone(payload_id, status, + operation_result_code); } void AnalyticsRecorder::OnBandwidthUpgradeStarted( @@ -625,8 +812,10 @@ void AnalyticsRecorder::OnBandwidthUpgradeStarted( } auto bandwidth_upgrade_attempt = std::make_unique(); - bandwidth_upgrade_attempt->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime())); + if (!no_record_time_millis_) { + 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); @@ -637,12 +826,19 @@ void AnalyticsRecorder::OnBandwidthUpgradeStarted( void AnalyticsRecorder::OnBandwidthUpgradeError( const std::string &endpoint_id, BandwidthUpgradeResult result, - BandwidthUpgradeErrorStage error_stage) { + BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code) { MutexLock lock(&mutex_); if (!CanRecordAnalyticsLocked("OnBandwidthUpgradeError")) { return; } - FinishUpgradeAttemptLocked(endpoint_id, result, error_stage); + // 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( @@ -652,7 +848,8 @@ void AnalyticsRecorder::OnBandwidthUpgradeSuccess( return; } FinishUpgradeAttemptLocked(endpoint_id, UPGRADE_RESULT_SUCCESS, - UPGRADE_SUCCESS); + UPGRADE_SUCCESS, + OperationResultCode::DETAIL_SUCCESS); } void AnalyticsRecorder::OnErrorCode(const ErrorCodeParams ¶ms) { @@ -744,20 +941,54 @@ void AnalyticsRecorder::LogSession() { return; } FinishStrategySessionLocked(); - client_session_->set_duration_millis(absl::ToInt64Milliseconds( - SystemClock::ElapsedRealtime() - started_client_session_time_)); + if (!no_record_time_millis_) { + client_session_->set_duration_millis(absl::ToInt64Milliseconds( + SystemClock::ElapsedRealtime() - started_client_session_time_)); + } LogClientSessionLocked(); LogEvent(STOP_CLIENT_SESSION); 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 + &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); + return params; +} + +std::unique_ptr +AnalyticsRecorder::BuildDiscoveryMetadataParams( + bool is_extended_advertisement_supported, int connected_ap_frequency, + bool is_nfc_available, + 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); + return params; +} + std::unique_ptr AnalyticsRecorder::BuildConnectionAttemptMetadataParams( ConnectionTechnology technology, ConnectionBand band, int frequency, int try_count, const std::string &network_operator, const std::string &country_code, bool is_tdls_used, bool wifi_hotspot_enabled, int max_wifi_tx_speed, int max_wifi_rx_speed, - int channel_width) { + int channel_width, OperationResultCode operation_result_code) { auto params = std::make_unique(); params->technology = technology; params->band = band; @@ -770,9 +1001,37 @@ AnalyticsRecorder::BuildConnectionAttemptMetadataParams( params->max_wifi_tx_speed = max_wifi_tx_speed; params->max_wifi_rx_speed = max_wifi_rx_speed; params->channel_width = channel_width; + params->operation_result_code = operation_result_code; return params; } +OperationResultCode AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium( + Medium medium) { + switch (medium) { + case Medium::BLUETOOTH: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_BT; + case Medium::WIFI_HOTSPOT: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_WIFI_HOTSPOT; + case Medium::BLE: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_BLE; + case Medium::BLE_L2CAP: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_BLE_L2CAP; + case Medium::WIFI_LAN: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_LAN; + case Medium::WIFI_AWARE: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_WIFI_AWARE; + case Medium::NFC: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_NFC; + case Medium::WIFI_DIRECT: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_WIFI_DIRECT; + case Medium::WEB_RTC: + return OperationResultCode::CONNECTIVITY_CHANNEL_IO_ERROR_ON_WEB_RTC; + default: + return OperationResultCode:: + CONNECTIVITY_CHANNEL_IO_ERROR_ON_UNKNOWN_MEDIUM; + } +} + bool AnalyticsRecorder::CanRecordAnalyticsLocked( absl::string_view method_name) { NEARBY_VLOG(1) << "AnalyticsRecorder LogEvent " << method_name @@ -855,16 +1114,23 @@ void AnalyticsRecorder::UpdateStrategySessionLocked( } } -void AnalyticsRecorder::RecordAdvertisingPhaseDurationLocked() const { +void AnalyticsRecorder::RecordAdvertisingPhaseDurationAndReasonLocked( + bool on_stop) const { if (current_advertising_phase_ == nullptr) { NEARBY_LOGS(INFO) << "Unable to record advertising phase duration due to " "null current_advertising_phase_"; return; } - if (!current_advertising_phase_->has_duration_millis()) { + if (!current_advertising_phase_->has_duration_millis() && + !no_record_time_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() { @@ -877,23 +1143,31 @@ void AnalyticsRecorder::FinishAdvertisingPhaseLocked() { MarkConnectionRequestIgnoredLocked(connection_request.get()); UpdateAdvertiserConnectionRequestLocked(connection_request.get()); } - RecordAdvertisingPhaseDurationLocked(); + RecordAdvertisingPhaseDurationAndReasonLocked(/* on_stop= */ false); *current_strategy_session_->add_advertising_phase() = *std::move(current_advertising_phase_); } incoming_connection_requests_.clear(); } -void AnalyticsRecorder::RecordDiscoveryPhaseDurationLocked() const { +void AnalyticsRecorder::RecordDiscoveryPhaseDurationAndReasonLocked( + bool on_stop) const { if (current_discovery_phase_ == nullptr) { NEARBY_LOGS(INFO) << "Unable to record discovery phase duration due to " "null current_discovery_phase_"; return; } - if (!current_discovery_phase_->has_duration_millis()) { + if (!current_discovery_phase_->has_duration_millis() && + !no_record_time_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() { @@ -906,7 +1180,7 @@ void AnalyticsRecorder::FinishDiscoveryPhaseLocked() { MarkConnectionRequestIgnoredLocked(connection_request.get()); UpdateDiscovererConnectionRequestLocked(connection_request.get()); } - RecordDiscoveryPhaseDurationLocked(); + RecordDiscoveryPhaseDurationAndReasonLocked(/* on_stop=*/false); *current_strategy_session_->add_discovery_phase() = *std::move(current_discovery_phase_); } @@ -922,9 +1196,11 @@ bool AnalyticsRecorder::UpdateAdvertiserConnectionRequestLocked( return false; } if (BothEndpointsRespondedLocked(request)) { - request->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - request->duration_millis()); + if (!no_record_time_millis_) { + request->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + request->duration_millis()); + } *current_advertising_phase_->add_received_connection_request() = *request; return true; } @@ -940,9 +1216,11 @@ bool AnalyticsRecorder::UpdateDiscovererConnectionRequestLocked( } if (BothEndpointsRespondedLocked(request) || request->local_response() == NOT_SENT) { - request->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - - request->duration_millis()); + if (!no_record_time_millis_) { + request->set_duration_millis( + absl::ToUnixMillis(SystemClock::ElapsedRealtime()) - + request->duration_millis()); + } *current_discovery_phase_->add_sent_connection_request() = *request; return true; } @@ -1004,9 +1282,62 @@ void AnalyticsRecorder::MarkConnectionRequestIgnoredLocked( } } +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, bool erase_item) { + BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code, bool erase_item) { if (current_strategy_session_ == nullptr) { NEARBY_LOGS(INFO) << "Unable to record upgrade attempt due to null " "current_strategy_session_"; @@ -1016,11 +1347,20 @@ void AnalyticsRecorder::FinishUpgradeAttemptLocked( 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()); + if (!no_record_time_millis_) { + 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( + ConvertToOperationResultCateory(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); @@ -1047,15 +1387,20 @@ void AnalyticsRecorder::FinishStrategySessionLocked() { // Finish any pending upgrade attempts. for (const auto &item : bandwidth_upgrade_attempts_) { - FinishUpgradeAttemptLocked(item.first, UNFINISHED_ERROR, - UPGRADE_UNFINISHED, /*erase_item=*/false); + 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_)); + if (!no_record_time_millis_) { + current_strategy_session_->set_duration_millis( + absl::ToInt64Milliseconds(SystemClock::ElapsedRealtime() - + started_strategy_session_time_)); + } *client_session_->add_strategy_session() = *std::move(current_strategy_session_); } @@ -1103,14 +1448,23 @@ void AnalyticsRecorder::PendingPayload::AddChunk( ConnectionsLog::Payload AnalyticsRecorder::PendingPayload::GetProtoPayload( PayloadStatus status) { ConnectionsLog::Payload payload; - payload.set_duration_millis( - absl::ToInt64Milliseconds(SystemClock::ElapsedRealtime() - start_time_)); + if (!no_record_time_millis_) { + 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( + ConvertToOperationResultCateory(operation_result_code_)); + payload.set_allocated_operation_result(operation_result_proto.release()); + return payload; } @@ -1125,9 +1479,19 @@ void AnalyticsRecorder::LogicalConnection::PhysicalConnectionEstablished( auto established_connection = std::make_unique(); established_connection->set_medium(medium); - established_connection->set_duration_millis( - absl::ToUnixMillis(SystemClock::ElapsedRealtime())); + if (!no_record_time_millis_) { + 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; } @@ -1215,7 +1579,8 @@ AnalyticsRecorder::LogicalConnection::GetEstablisedConnections() { 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)}); + {payload_id, std::make_unique(type, total_size_bytes, + no_record_time_millis_)}); } void AnalyticsRecorder::LogicalConnection::ChunkReceived( @@ -1229,7 +1594,8 @@ void AnalyticsRecorder::LogicalConnection::ChunkReceived( } void AnalyticsRecorder::LogicalConnection::IncomingPayloadDone( - std::int64_t payload_id, PayloadStatus status) { + std::int64_t payload_id, PayloadStatus status, + OperationResultCode operation_result_code) { if (current_medium_ == UNKNOWN_MEDIUM) { NEARBY_LOGS(WARNING) << "Unexpected call to incomingPayloadDone() while " "AnalyticsRecorder has no active current medium."; @@ -1241,6 +1607,7 @@ void AnalyticsRecorder::LogicalConnection::IncomingPayloadDone( &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); @@ -1251,7 +1618,8 @@ void AnalyticsRecorder::LogicalConnection::IncomingPayloadDone( 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)}); + {payload_id, std::make_unique(type, total_size_bytes, + no_record_time_millis_)}); } void AnalyticsRecorder::LogicalConnection::ChunkSent(std::int64_t payload_id, @@ -1265,7 +1633,8 @@ void AnalyticsRecorder::LogicalConnection::ChunkSent(std::int64_t payload_id, } void AnalyticsRecorder::LogicalConnection::OutgoingPayloadDone( - std::int64_t payload_id, PayloadStatus status) { + std::int64_t payload_id, PayloadStatus status, + OperationResultCode operation_result_code) { if (current_medium_ == UNKNOWN_MEDIUM) { NEARBY_LOGS(WARNING) << "Unexpected call to outgoingPayloadDone() while " "AnalyticsRecorder has no active current medium."; @@ -1277,6 +1646,7 @@ void AnalyticsRecorder::LogicalConnection::OutgoingPayloadDone( &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); @@ -1289,9 +1659,11 @@ void AnalyticsRecorder::LogicalConnection::FinishPhysicalConnection( 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()); + if (!no_record_time_millis_) { + 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 = @@ -1316,8 +1688,12 @@ AnalyticsRecorder::LogicalConnection::ResolvePendingPayloads( 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); @@ -1325,7 +1701,8 @@ AnalyticsRecorder::LogicalConnection::ResolvePendingPayloads( upgraded_payloads.insert( {item.first, std::make_unique( - pending_payload->type(), pending_payload->total_size_bytes())}); + pending_payload->type(), pending_payload->total_size_bytes(), + no_record_time_millis_, operation_result_code)}); } } pending_payloads.clear(); @@ -1340,6 +1717,26 @@ AnalyticsRecorder::LogicalConnection::ResolvePendingPayloads( 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::GetOperationResultCateory( + location::nearby::proto::connections::OperationResultCode result_code) { + return ConvertToOperationResultCateory(result_code); +} + void AnalyticsRecorder::Sync() { CountDownLatch latch(1); serial_executor_.Execute([&]() { latch.CountDown(); }); diff --git a/connections/implementation/analytics/analytics_recorder.h b/connections/implementation/analytics/analytics_recorder.h index 7145f1ac5f..eed3b4eac3 100644 --- a/connections/implementation/analytics/analytics_recorder.h +++ b/connections/implementation/analytics/analytics_recorder.h @@ -25,7 +25,9 @@ #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" @@ -42,21 +44,25 @@ namespace analytics { class AnalyticsRecorder { public: explicit AnalyticsRecorder(::nearby::analytics::EventLogger *event_logger); + // For testing only. + AnalyticsRecorder(::nearby::analytics::EventLogger *event_logger, + bool no_record_time_millis); virtual ~AnalyticsRecorder(); - // TODO(edwinwu): Implement to pass real values for AdvertisingMetadata and - // DiscoveryMetaData: is_extended_advertisement_supported, - // connected_ap_frequency, and is_nfc_available. Set as default values for - // analytics recorder. // Advertising phase void OnStartAdvertising( connections::Strategy strategy, const std::vector &mediums, - bool is_extended_advertisement_supported = false, - int connected_ap_frequency = 0, bool is_nfc_available = false) + AdvertisingMetadataParams *advertising_metadata_params) ABSL_LOCKS_EXCLUDED(mutex_); void OnStopAdvertising() ABSL_LOCKS_EXCLUDED(mutex_); + // 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_); + // Connection listening void OnStartedIncomingConnectionListening(connections::Strategy strategy) ABSL_LOCKS_EXCLUDED(mutex_); @@ -66,10 +72,15 @@ class AnalyticsRecorder { void OnStartDiscovery( connections::Strategy strategy, const std::vector &mediums, - bool is_extended_advertisement_supported = false, - int connected_ap_frequency = 0, bool is_nfc_available = false) + DiscoveryMetadataParams *discovery_metadata_params) ABSL_LOCKS_EXCLUDED(mutex_); void OnStopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_); + + // 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_); @@ -92,6 +103,8 @@ class AnalyticsRecorder { ABSL_LOCKS_EXCLUDED(mutex_); // Connection attempt + // Records an attempt with meta data at establishing an incoming physical + // connection. void OnIncomingConnectionAttempt( location::nearby::proto::connections::ConnectionAttemptType type, location::nearby::proto::connections::Medium medium, @@ -99,6 +112,8 @@ class AnalyticsRecorder { 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( const std::string &remote_endpoint_id, location::nearby::proto::connections::ConnectionAttemptType type, @@ -107,9 +122,20 @@ class AnalyticsRecorder { absl::Duration duration, const std::string &connection_token, ConnectionAttemptMetadataParams *connection_attempt_metadata_params) ABSL_LOCKS_EXCLUDED(mutex_); - // TODO(edwinwu): Implement network operator, country code, tdls, wifi hotspot - //, max wifi tx/rx speed and channel width. Set as default values for - // analytics recorder. + static std::unique_ptr + BuildAdvertisingMetadataParams( + bool is_extended_advertisement_supported = false, + int connected_ap_frequency = 0, bool is_nfc_available = false, + 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 + &operation_result_with_mediums = {}); + static std::unique_ptr BuildConnectionAttemptMetadataParams( location::nearby::proto::connections::ConnectionTechnology technology, @@ -117,7 +143,13 @@ class AnalyticsRecorder { int try_count, const std::string &network_operator = {}, const std::string &country_code = {}, bool is_tdls_used = false, bool wifi_hotspot_enabled = false, int max_wifi_tx_speed = 0, - int max_wifi_rx_speed = 0, int channel_width = -1); + int max_wifi_rx_speed = 0, int channel_width = -1, + location::nearby::proto::connections::OperationResultCode + operation_result_code = location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN); + static location::nearby::proto::connections::OperationResultCode + GetChannelIoErrorResultCodeFromMedium( + location::nearby::proto::connections::Medium medium); // Connection establishedSafeDisconnectionResult void OnConnectionEstablished( @@ -144,8 +176,9 @@ class AnalyticsRecorder { ABSL_LOCKS_EXCLUDED(mutex_); void OnIncomingPayloadDone( const std::string &endpoint_id, std::int64_t payload_id, - location::nearby::proto::connections::PayloadStatus status) - ABSL_LOCKS_EXCLUDED(mutex_); + 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, @@ -157,8 +190,9 @@ class AnalyticsRecorder { ABSL_LOCKS_EXCLUDED(mutex_); void OnOutgoingPayloadDone( const std::string &endpoint_id, std::int64_t payload_id, - location::nearby::proto::connections::PayloadStatus status) - ABSL_LOCKS_EXCLUDED(mutex_); + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_); // BandwidthUpgrade void OnBandwidthUpgradeStarted( @@ -172,7 +206,9 @@ class AnalyticsRecorder { const std::string &endpoint_id, location::nearby::proto::connections::BandwidthUpgradeResult result, location::nearby::proto::connections::BandwidthUpgradeErrorStage - error_stage) ABSL_LOCKS_EXCLUDED(mutex_); + 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_); @@ -180,7 +216,7 @@ class AnalyticsRecorder { void OnErrorCode(const ErrorCodeParams ¶ms); // Log the start client session event with start client session logging - // resouces setup (e.g. client_session_, started_client_session_time_) + // resources setup (e.g. client_session_, started_client_session_time_) void LogStartSession() ABSL_LOCKS_EXCLUDED(mutex_); // Invokes event_logger_.Log() at the end of life of client. Log action is @@ -190,6 +226,10 @@ class AnalyticsRecorder { bool IsSessionLogged(); + location::nearby::proto::connections::OperationResultCategory + GetOperationResultCateory( + location::nearby::proto::connections::OperationResultCode result_code); + // Waits until all logs are sent to the backend. // For testing only. void Sync(); @@ -199,12 +239,21 @@ class AnalyticsRecorder { class PendingPayload { public: PendingPayload(location::nearby::proto::connections::PayloadType type, - std::int64_t total_size_bytes) + std::int64_t total_size_bytes, bool no_record_time_millis) + : PendingPayload(type, total_size_bytes, no_record_time_millis, + location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN) {} + PendingPayload(location::nearby::proto::connections::PayloadType type, + std::int64_t total_size_bytes, bool no_record_time_millis, + 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) {} + num_chunks_(0), + operation_result_code_(operation_result_code), + no_record_time_millis_(no_record_time_millis) {} ~PendingPayload() = default; void AddChunk(std::int64_t chunk_size_bytes); @@ -218,19 +267,31 @@ class AnalyticsRecorder { 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; + // For testing only. + bool no_record_time_millis_ = false; }; class LogicalConnection { public: LogicalConnection( location::nearby::proto::connections::Medium initial_medium, - const std::string &connection_token) { + const std::string &connection_token, bool no_record_time_millis) + : no_record_time_millis_(no_record_time_millis) { PhysicalConnectionEstablished(initial_medium, connection_token); } LogicalConnection(const LogicalConnection &) = delete; @@ -260,7 +321,9 @@ class AnalyticsRecorder { 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::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); void OutgoingPayloadStarted( std::int64_t payload_id, location::nearby::proto::connections::PayloadType type, @@ -268,7 +331,9 @@ class AnalyticsRecorder { 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::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); std::vector @@ -286,6 +351,9 @@ class AnalyticsRecorder { 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; @@ -297,6 +365,8 @@ class AnalyticsRecorder { incoming_payloads_; absl::btree_map> outgoing_payloads_; + // For testing only. + bool no_record_time_millis_ = false; }; bool CanRecordAnalyticsLocked(absl::string_view method_name) @@ -312,10 +382,10 @@ class AnalyticsRecorder { connections::Strategy strategy, location::nearby::proto::connections::SessionRole role) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void RecordAdvertisingPhaseDurationLocked() const + void RecordAdvertisingPhaseDurationAndReasonLocked(bool on_stop) const ABSL_SHARED_LOCKS_REQUIRED(mutex_); void FinishAdvertisingPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void RecordDiscoveryPhaseDurationLocked() const + void RecordDiscoveryPhaseDurationAndReasonLocked(bool on_stop) const ABSL_SHARED_LOCKS_REQUIRED(mutex_); void FinishDiscoveryPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); bool UpdateAdvertiserConnectionRequestLocked( @@ -338,11 +408,43 @@ class AnalyticsRecorder { 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_); @@ -351,6 +453,11 @@ class AnalyticsRecorder { void ResetClientSessionLoggingResoucesLocked() 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 @@ -364,6 +471,9 @@ class AnalyticsRecorder { // Protects all sub-protos reading and writing in ConnectionLog. Mutex mutex_; + // For testing only. + bool no_record_time_millis_ = false; + // ClientSession std::unique_ptr< location::nearby::analytics::proto::ConnectionsLog::ClientSession> diff --git a/connections/implementation/analytics/analytics_recorder_test.cc b/connections/implementation/analytics/analytics_recorder_test.cc index a2bc091edf..04e5cbcbce 100644 --- a/connections/implementation/analytics/analytics_recorder_test.cc +++ b/connections/implementation/analytics/analytics_recorder_test.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -25,6 +26,9 @@ #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/connection_attempt_metadata_params.h" +#include "connections/payload_type.h" +#include "connections/strategy.h" #include "internal/analytics/mock_event_logger.h" #include "internal/platform/count_down_latch.h" #include "internal/platform/error_code_params.h" @@ -55,6 +59,8 @@ using ::location::nearby::proto::connections::INCOMING; using ::location::nearby::proto::connections::INITIAL; using ::location::nearby::proto::connections::LOCAL_DISCONNECTION; using ::location::nearby::proto::connections::Medium; +using ::location::nearby::proto::connections::OperationResultCategory; +using ::location::nearby::proto::connections::OperationResultCode; using ::location::nearby::proto::connections::RESULT_ERROR; using ::location::nearby::proto::connections::RESULT_SUCCESS; using ::location::nearby::proto::connections::START_CLIENT_SESSION; @@ -72,7 +78,6 @@ using ::proto2::contrib::parse_proto::ParseTextProtoOrDie; using ::testing::Contains; using ::protobuf_matchers::EqualsProto; using ::testing::Not; -using ::testing::proto::Partially; constexpr absl::Duration kDefaultTimeout = absl::Milliseconds(1000); @@ -142,7 +147,8 @@ class FakeEventLogger : public MockEventLogger { TEST(AnalyticsRecorderTest, SessionOnlyLoggedOnceWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); analytics_recorder.LogSession(); analytics_recorder.LogSession(); @@ -159,41 +165,68 @@ TEST(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedAdvertisingCalls) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - - analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLE, BLUETOOTH}); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLUETOOTH); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + advertising_metadata_params->operation_result_with_mediums = { + operation_result}; + analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); - analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLUETOOTH}); + operation_result.set_medium(BLE); + advertising_metadata_params->operation_result_with_mediums = { + operation_result}; + analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.LogSession(); ASSERT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result()); ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: CLIENT_STOP_ADVERTISING + } + advertising_phase { medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + adv_dis_result { + medium: BLE + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + (EqualsProto(strategy_session_proto))); } TEST(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedDiscoveryCalls) { @@ -201,51 +234,87 @@ TEST(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedDiscoveryCalls) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - - analytics_recorder.OnStartDiscovery( - strategy, /*mediums=*/{BLE, BLUETOOTH}, - /*is_extended_advertisement_supported=*/true, - /*connected_ap_frequency=*/1, /*is_nfc_available=*/false); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::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; + operation_result2.set_medium(BLE); + operation_result2.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result2.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams( + /*is_extended_advertisement_supported*/ true, + /*connected_ap_frequency*/ 1, /*is_nfc_available=*/false, + {operation_result, operation_result2}); + analytics_recorder.OnStartDiscovery(strategy, /*mediums=*/{BLE, BLUETOOTH}, + discovery_metadata_params.get()); analytics_recorder.OnStopDiscovery(); analytics_recorder.OnEndpointFound(BLUETOOTH); analytics_recorder.OnEndpointFound(BLE); - analytics_recorder.OnStartDiscovery( - strategy, /*mediums=*/{BLUETOOTH}, - /*is_extended_advertisement_supported=*/true, - /*connected_ap_frequency=*/1, /*is_nfc_available=*/false); + + auto discovery_metadata_params2 = + analytics_recorder.BuildDiscoveryMetadataParams( + /*is_extended_advertisement_supported*/ true, + /*connected_ap_frequency*/ 1, /*is_nfc_available=*/false, + {operation_result}); + analytics_recorder.OnStartDiscovery(strategy, /*mediums=*/{BLUETOOTH}, + discovery_metadata_params2.get()); analytics_recorder.LogSession(); ASSERT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result()); ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovered_endpoint < medium: BLUETOOTH > - discovered_endpoint < medium: BLE > - discovery_metadata < + discovered_endpoint { medium: BLUETOOTH } + discovered_endpoint { medium: BLE } + discovery_metadata { supports_extended_ble_advertisements: true connected_ap_frequency: 1 supports_nfc_technology: false - > - > - discovery_phase < + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + adv_dis_result { + medium: BLE + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: CLIENT_STOP_DISCOVERING + } + discovery_phase { medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: true connected_ap_frequency: 1 supports_nfc_technology: false - > - > - >)pb"); + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_DISCOVERING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, @@ -255,18 +324,28 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - - analytics_recorder.OnStartAdvertising(strategy, mediums); - analytics_recorder.OnStartDiscovery(strategy, mediums); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + analytics_recorder.OnStartAdvertising(strategy, mediums, + advertising_metadata_params.get()); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); + analytics_recorder.OnStartDiscovery(strategy, mediums, + discovery_metadata_params.get()); analytics_recorder.OnStopAdvertising(); analytics_recorder.OnStopDiscovery(); - analytics_recorder.OnStartAdvertising(strategy, mediums); + analytics_recorder.OnStartAdvertising(strategy, mediums, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); - analytics_recorder.OnStartDiscovery(strategy, mediums); + analytics_recorder.OnStartDiscovery(strategy, mediums, + discovery_metadata_params.get()); analytics_recorder.OnStopDiscovery(); - analytics_recorder.OnStartDiscovery(strategy, mediums); - analytics_recorder.OnStartAdvertising(strategy, mediums); + analytics_recorder.OnStartDiscovery(strategy, mediums, {}); + analytics_recorder.OnStartAdvertising(strategy, mediums, + advertising_metadata_params.get()); analytics_recorder.OnStopDiscovery(); analytics_recorder.OnStopAdvertising(); @@ -279,68 +358,74 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - discovery_phase < + } + stop_reason: CLIENT_STOP_DISCOVERING + } + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - discovery_phase < + } + stop_reason: CLIENT_STOP_DISCOVERING + } + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + stop_reason: CLIENT_STOP_DISCOVERING + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + stop_reason: CLIENT_STOP_ADVERTISING + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + stop_reason: CLIENT_STOP_ADVERTISING + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + stop_reason: CLIENT_STOP_ADVERTISING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, AdvertiserConnectionRequestsWorks) { @@ -351,10 +436,21 @@ TEST(AnalyticsRecorderTest, AdvertiserConnectionRequestsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLE); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + advertising_metadata_params->operation_result_with_mediums = { + operation_result}; analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnConnectionRequestReceived(endpoint_id_0); analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0); analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0); @@ -376,38 +472,44 @@ TEST(AnalyticsRecorderTest, AdvertiserConnectionRequestsWorks) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - received_connection_request < + } + adv_dis_result { + medium: BLE + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + received_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - received_connection_request < + } + received_connection_request { local_response: ACCEPTED remote_response: REJECTED - > - received_connection_request < + } + received_connection_request { local_response: REJECTED remote_response: ACCEPTED - > - received_connection_request < + } + received_connection_request { local_response: REJECTED remote_response: REJECTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, DiscoveryConnectionRequestsWorks) { @@ -418,10 +520,20 @@ TEST(AnalyticsRecorderTest, DiscoveryConnectionRequestsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLUETOOTH); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); + discovery_metadata_params->operation_result_with_mediums = {operation_result}; analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + discovery_metadata_params.get()); analytics_recorder.OnConnectionRequestSent(endpoint_id_0); analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0); @@ -444,38 +556,44 @@ TEST(AnalyticsRecorderTest, DiscoveryConnectionRequestsWorks) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_DISCOVERING + sent_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - sent_connection_request < + } + sent_connection_request { local_response: ACCEPTED remote_response: REJECTED - > - sent_connection_request < + } + sent_connection_request { local_response: REJECTED remote_response: ACCEPTED - > - sent_connection_request < + } + sent_connection_request { local_response: REJECTED remote_response: REJECTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, @@ -486,10 +604,21 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLUETOOTH); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + advertising_metadata_params->operation_result_with_mediums = { + operation_result}; analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); // Ignored by local. analytics_recorder.OnConnectionRequestReceived(endpoint_id_0); analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0); @@ -506,34 +635,40 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - received_connection_request < + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + received_connection_request { local_response: IGNORED remote_response: ACCEPTED - > - received_connection_request < + } + received_connection_request { local_response: ACCEPTED remote_response: IGNORED - > - received_connection_request < + } + received_connection_request { local_response: IGNORED remote_response: IGNORED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, @@ -544,10 +679,20 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLUETOOTH); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); + discovery_metadata_params->operation_result_with_mediums = {operation_result}; analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + discovery_metadata_params.get()); // Ignored by local. analytics_recorder.OnConnectionRequestSent(endpoint_id_0); @@ -565,46 +710,68 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + stop_reason: FINISH_SESSION_STOP_DISCOVERING + sent_connection_request { local_response: IGNORED remote_response: ACCEPTED - > - sent_connection_request < + } + sent_connection_request { local_response: ACCEPTED remote_response: IGNORED - > - sent_connection_request < + } + sent_connection_request { local_response: IGNORED remote_response: IGNORED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, SuccessfulIncomingConnectionAttempt) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); - + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + ConnectionsLog::OperationResultWithMedium operation_result; + operation_result.set_medium(BLUETOOTH); + operation_result.set_result_code(OperationResultCode::DETAIL_SUCCESS); + operation_result.set_result_category( + OperationResultCategory::CATEGORY_SUCCESS); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + advertising_metadata_params->operation_result_with_mediums = { + operation_result}; analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); + + auto connections_attempt_metadata_params = + std::make_unique(); + connections_attempt_metadata_params->operation_result_code = + OperationResultCode::DETAIL_SUCCESS; analytics_recorder.OnIncomingConnectionAttempt( INITIAL, BLUETOOTH, RESULT_SUCCESS, absl::Duration{}, - /*connection_token=*/"", nullptr); + /*connection_token=*/"", connections_attempt_metadata_params.get()); analytics_recorder.OnStopAdvertising(); analytics_recorder.LogSession(); @@ -612,25 +779,31 @@ TEST(AnalyticsRecorderTest, SuccessfulIncomingConnectionAttempt) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - connection_attempt < + } + stop_reason: CLIENT_STOP_ADVERTISING + adv_dis_result { + medium: BLUETOOTH + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + connection_attempt { type: INITIAL direction: INCOMING medium: BLUETOOTH attempt_result: RESULT_SUCCESS connection_token: "" - connection_attempt_metadata < + connection_attempt_metadata { technology: CONNECTION_TECHNOLOGY_UNKNOWN_TECHNOLOGY band: CONNECTION_BAND_UNKNOWN_BAND frequency: -1 @@ -642,12 +815,16 @@ TEST(AnalyticsRecorderTest, SuccessfulIncomingConnectionAttempt) { max_tx_speed: 0 max_rx_speed: 0 wifi_channel_width: -1 - > - > - >)pb"); + } + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, @@ -656,7 +833,8 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); auto connections_attempt_metadata_params = analytics_recorder.BuildConnectionAttemptMetadataParams( @@ -667,9 +845,13 @@ TEST(AnalyticsRecorderTest, /*frequency*/ 2400, /*try_count*/ 0, /*network_operator*/ {}, /*country_code*/ {}, /*is_tdls_used*/ false, /*wifi_hotspot_enabled*/ false, /*max_wifi_tx_speed*/ 0, - /*max_wifi_rx_speed*/ 0, /*channel_width*/ 0); + /*max_wifi_rx_speed*/ 0, /*channel_width*/ 0, + OperationResultCode::CONNECTIVITY_BT_CLIENT_SOCKET_CREATION_FAILURE); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + discovery_metadata_params.get()); analytics_recorder.OnConnectionRequestSent(endpoint_id); analytics_recorder.OnOutgoingConnectionAttempt( endpoint_id, INITIAL, BLUETOOTH, RESULT_ERROR, absl::Duration{}, @@ -680,29 +862,30 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + stop_reason: FINISH_SESSION_STOP_DISCOVERING + sent_connection_request { local_response: NOT_SENT remote_response: NOT_SENT - > - > - connection_attempt < + } + } + connection_attempt { type: INITIAL direction: OUTGOING medium: BLUETOOTH attempt_result: RESULT_ERROR connection_token: "" - connection_attempt_metadata < + connection_attempt_metadata { technology: CONNECTION_TECHNOLOGY_HOTSPOT_LOCALONLY band: CONNECTION_BAND_WIFI_BAND_6GHZ frequency: 2400 @@ -714,12 +897,16 @@ TEST(AnalyticsRecorderTest, max_tx_speed: 0 max_rx_speed: 0 wifi_channel_width: 0 - > - > - >)pb"); + } + operation_result { + result_category: CATEGORY_CONNECTIVITY_ERROR + result_code: CONNECTIVITY_BT_CLIENT_SOCKET_CREATION_FAILURE + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, UnfinishedEstablishedConnectionsAddedAsUnfinished) { @@ -728,15 +915,19 @@ TEST(AnalyticsRecorderTest, UnfinishedEstablishedConnectionsAddedAsUnfinished) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnConnectionEstablished(endpoint_id, BLUETOOTH, connection_token); analytics_recorder.OnConnectionClosed( - endpoint_id, BLUETOOTH, UPGRADED, ConnectionsLog::EstablishedConnection:: - UNKNOWN_SAFE_DISCONNECTION_RESULT); + endpoint_id, BLUETOOTH, UPGRADED, + ConnectionsLog::EstablishedConnection::UNKNOWN_SAFE_DISCONNECTION_RESULT); analytics_recorder.OnConnectionEstablished(endpoint_id, WIFI_LAN, connection_token); @@ -745,32 +936,43 @@ TEST(AnalyticsRecorderTest, UnfinishedEstablishedConnectionsAddedAsUnfinished) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - established_connection < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + established_connection { medium: BLUETOOTH disconnection_reason: UPGRADED connection_token: "connection_token" - > - established_connection < + safe_disconnection_result: UNKNOWN_SAFE_DISCONNECTION_RESULT + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + established_connection { medium: WIFI_LAN disconnection_reason: UNFINISHED connection_token: "connection_token" - > - >)pb"); + safe_disconnection_result: SAFE_DISCONNECTION + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { @@ -780,10 +982,14 @@ TEST(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnConnectionEstablished(endpoint_id, BLUETOOTH, connection_token); analytics_recorder.OnOutgoingPayloadStarted( @@ -798,57 +1004,76 @@ TEST(AnalyticsRecorderTest, OutgoingPayloadUpgraded) { analytics_recorder.OnPayloadChunkSent(endpoint_id, payload_id, 10); analytics_recorder.OnPayloadChunkSent(endpoint_id, payload_id, 10); analytics_recorder.OnPayloadChunkSent(endpoint_id, payload_id, 10); - analytics_recorder.OnOutgoingPayloadDone(endpoint_id, payload_id, SUCCESS); - analytics_recorder.OnConnectionClosed(endpoint_id, WIFI_LAN, - LOCAL_DISCONNECTION, - ConnectionsLog::EstablishedConnection:: - SAFE_DISCONNECTION); + analytics_recorder.OnOutgoingPayloadDone(endpoint_id, payload_id, SUCCESS, + OperationResultCode::DETAIL_SUCCESS); + analytics_recorder.OnConnectionClosed( + endpoint_id, WIFI_LAN, LOCAL_DISCONNECTION, + ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION); analytics_recorder.LogSession(); ASSERT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result()); ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - established_connection < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + established_connection { medium: BLUETOOTH - sent_payload < + sent_payload { type: FILE total_size_bytes: 50 num_bytes_transferred: 20 num_chunks: 2 status: MOVED_TO_NEW_MEDIUM - > + operation_result { + result_category: CATEGORY_MISCELLANEOUS + result_code: MISCELLEANEOUS_MOVE_TO_NEW_MEDIUM + } + } disconnection_reason: UPGRADED connection_token: "connection_token" - > - established_connection < + safe_disconnection_result: SAFE_DISCONNECTION + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + established_connection { medium: WIFI_LAN - sent_payload < + sent_payload { type: FILE total_size_bytes: 50 num_bytes_transferred: 30 num_chunks: 3 status: SUCCESS - > + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } disconnection_reason: LOCAL_DISCONNECTION connection_token: "connection_token" - > - >)pb"); + safe_disconnection_result: SAFE_DISCONNECTION + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, UpgradeAttemptWorks) { @@ -859,10 +1084,14 @@ TEST(AnalyticsRecorderTest, UpgradeAttemptWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnBandwidthUpgradeStarted(endpoint_id, BLE, WIFI_LAN, INCOMING, connection_token); @@ -870,8 +1099,9 @@ TEST(AnalyticsRecorderTest, UpgradeAttemptWorks) { analytics_recorder.OnBandwidthUpgradeStarted( endpoint_id_1, BLUETOOTH, WIFI_LAN, INCOMING, connection_token); // Error to upgrade. - analytics_recorder.OnBandwidthUpgradeError(endpoint_id, WIFI_LAN_MEDIUM_ERROR, - WIFI_LAN_SOCKET_CREATION); + analytics_recorder.OnBandwidthUpgradeError( + endpoint_id, WIFI_LAN_MEDIUM_ERROR, WIFI_LAN_SOCKET_CREATION, + OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL); // Success to upgrade. analytics_recorder.OnBandwidthUpgradeSuccess(endpoint_id_1); // Upgrade is unfinished. @@ -883,34 +1113,43 @@ TEST(AnalyticsRecorderTest, UpgradeAttemptWorks) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - upgrade_attempt < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + upgrade_attempt { direction: INCOMING from_medium: BLE to_medium: WIFI_LAN upgrade_result: WIFI_LAN_MEDIUM_ERROR error_stage: WIFI_LAN_SOCKET_CREATION connection_token: "connection_token" - > - upgrade_attempt < + operation_result { + result_category: CATEGORY_CONNECTIVITY_ERROR + result_code: CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL + } + } + upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH to_medium: WIFI_LAN upgrade_result: UPGRADE_RESULT_SUCCESS error_stage: UPGRADE_SUCCESS connection_token: "connection_token" - > + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH @@ -918,11 +1157,15 @@ TEST(AnalyticsRecorderTest, UpgradeAttemptWorks) { upgrade_result: UNFINISHED_ERROR error_stage: UPGRADE_UNFINISHED connection_token: "connection_token" + operation_result { + result_category: CATEGORY_DEVICE_STATE_ERROR + result_code: DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS + } } - >)pb"); + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { @@ -933,7 +1176,8 @@ TEST(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); analytics_recorder.OnStartedIncomingConnectionListening( connections::Strategy::kP2pStar); @@ -944,8 +1188,9 @@ TEST(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { analytics_recorder.OnBandwidthUpgradeStarted( endpoint_id_1, BLUETOOTH, WIFI_LAN, INCOMING, connection_token); // Error to upgrade. - analytics_recorder.OnBandwidthUpgradeError(endpoint_id, WIFI_LAN_MEDIUM_ERROR, - WIFI_LAN_SOCKET_CREATION); + analytics_recorder.OnBandwidthUpgradeError( + endpoint_id, WIFI_LAN_MEDIUM_ERROR, WIFI_LAN_SOCKET_CREATION, + OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL); // Success to upgrade. analytics_recorder.OnBandwidthUpgradeSuccess(endpoint_id_1); @@ -954,38 +1199,51 @@ TEST(AnalyticsRecorderTest, StartListeningForIncomingConnectionsWorks) { ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - upgrade_attempt < + upgrade_attempt { direction: INCOMING from_medium: BLE to_medium: WIFI_LAN upgrade_result: WIFI_LAN_MEDIUM_ERROR error_stage: WIFI_LAN_SOCKET_CREATION connection_token: "connection_token" - > - upgrade_attempt < + operation_result { + result_category: CATEGORY_CONNECTIVITY_ERROR + result_code: CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL + } + } + upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH to_medium: WIFI_LAN upgrade_result: UPGRADE_RESULT_SUCCESS error_stage: UPGRADE_SUCCESS connection_token: "connection_token" - > - >)pb"); + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); analytics_recorder.Sync(); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectly) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{WEB_RTC}); + /*mediums=*/{WEB_RTC}, + discovery_metadata_params.get()); ErrorCodeParams error_code_params = ErrorCodeRecorder::BuildErrorCodeParams( WEB_RTC, DISCONNECT, DISCONNECT_NETWORK_FAILED, @@ -1003,16 +1261,20 @@ TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectly) { connection_token: "connection_token" )pb"); - EXPECT_THAT(event_logger.GetErrorCode(), - Partially(EqualsProto(error_code_proto))); + EXPECT_THAT(event_logger.GetErrorCode(), EqualsProto(error_code_proto)); } TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForUnknownDescription) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLUETOOTH}); + /*mediums=*/{BLUETOOTH}, + discovery_metadata_params.get()); ErrorCodeParams error_code_params; // Skip setting error_code_params.description @@ -1033,16 +1295,20 @@ TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForUnknownDescription) { connection_token: "connection_token" )pb"); - EXPECT_THAT(event_logger.GetErrorCode(), - Partially(EqualsProto(error_code_proto))); + EXPECT_THAT(event_logger.GetErrorCode(), EqualsProto(error_code_proto)); } TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForCommonError) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLUETOOTH}); + /*mediums=*/{BLUETOOTH}, + discovery_metadata_params.get()); ErrorCodeParams error_code_params = ErrorCodeRecorder::BuildErrorCodeParams( BLUETOOTH, START_DISCOVERING, INVALID_PARAMETER, @@ -1060,14 +1326,14 @@ TEST(AnalyticsRecorderTest, SetErrorCodeFieldsCorrectlyForCommonError) { connection_token: "connection_token" )pb"); - EXPECT_THAT(event_logger.GetErrorCode(), - Partially(EqualsProto(error_code_proto))); + EXPECT_THAT(event_logger.GetErrorCode(), EqualsProto(error_code_proto)); } TEST(AnalyticsRecorderTest, CheckIfSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); // LogSession to count down client_session_done_latch. analytics_recorder.LogSession(); @@ -1083,7 +1349,8 @@ TEST(AnalyticsRecorderTest, ConstructAnalyticsRecorder) { &start_client_session_done_latch); // Call the constructor to count down the session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); std::vector event_types = event_logger.GetLoggedEventTypes(); @@ -1099,7 +1366,8 @@ TEST(AnalyticsRecorderTest, &start_client_session_done_latch); // Call the constructor to count down the start_client_session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); // Log start client session once. @@ -1128,7 +1396,8 @@ TEST(AnalyticsRecorderTest, &start_client_session_done_latch); // Call the constructor to count down the start_client_session_done_latch. - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); ASSERT_TRUE(start_client_session_done_latch.Await(kDefaultTimeout).result()); // Log start client session once. @@ -1165,10 +1434,14 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnConnectionRequestReceived(endpoint_id_0); analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0); analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0); @@ -1179,26 +1452,27 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - received_connection_request < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + received_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1224,42 +1498,42 @@ TEST(AnalyticsRecorderTest, // received_connection_request) will append to the strategy_session) ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie( R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - received_connection_request < + } + received_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - advertising_phase < + } + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - received_connection_request < + } + received_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - received_connection_request < + } + received_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } TEST(AnalyticsRecorderTest, @@ -1268,10 +1542,14 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams(); analytics_recorder.OnStartDiscovery(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + discovery_metadata_params.get()); analytics_recorder.OnConnectionRequestSent(endpoint_id_0); analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0); @@ -1283,26 +1561,27 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + stop_reason: FINISH_SESSION_STOP_DISCOVERING + sent_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1328,42 +1607,42 @@ TEST(AnalyticsRecorderTest, // sent_connection_request) will append to the strategy_session) ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + sent_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - discovery_phase < + } + } + discovery_phase { medium: BLE medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - sent_connection_request < + } + sent_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - sent_connection_request < + } + sent_connection_request { local_response: ACCEPTED remote_response: ACCEPTED - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } TEST(AnalyticsRecorderTest, ClearcActiveConnectionsAfterSessionWasLogged) { @@ -1374,9 +1653,13 @@ TEST(AnalyticsRecorderTest, ClearcActiveConnectionsAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); - analytics_recorder.OnStartAdvertising(strategy, mediums); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); + analytics_recorder.OnStartAdvertising(strategy, mediums, + advertising_metadata_params.get()); analytics_recorder.OnConnectionEstablished(endpoint_id, BLUETOOTH, connection_token); @@ -1386,27 +1669,33 @@ TEST(AnalyticsRecorderTest, ClearcActiveConnectionsAfterSessionWasLogged) { ASSERT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result()); ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - established_connection < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + established_connection { medium: BLUETOOTH disconnection_reason: UNFINISHED connection_token: "connection_token" - > - >)pb"); + safe_disconnection_result: SAFE_DISCONNECTION + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1428,36 +1717,41 @@ TEST(AnalyticsRecorderTest, ClearcActiveConnectionsAfterSessionWasLogged) { // established_connection) will stay there. ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - established_connection < + } + } + established_connection { medium: BLUETOOTH disconnection_reason: UNFINISHED connection_token: "connection_token" - > - >)pb"); + safe_disconnection_result: SAFE_DISCONNECTION + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } TEST(AnalyticsRecorderTest, @@ -1469,10 +1763,14 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnBandwidthUpgradeStarted(endpoint_id, BLE, WIFI_LAN, INCOMING, connection_token); @@ -1480,8 +1778,9 @@ TEST(AnalyticsRecorderTest, analytics_recorder.OnBandwidthUpgradeStarted( endpoint_id_1, BLUETOOTH, WIFI_LAN, INCOMING, connection_token); // - Error to upgrade. - analytics_recorder.OnBandwidthUpgradeError(endpoint_id, WIFI_LAN_MEDIUM_ERROR, - WIFI_LAN_SOCKET_CREATION); + analytics_recorder.OnBandwidthUpgradeError( + endpoint_id, WIFI_LAN_MEDIUM_ERROR, WIFI_LAN_SOCKET_CREATION, + OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL); // - Success to upgrade. analytics_recorder.OnBandwidthUpgradeSuccess(endpoint_id_1); @@ -1498,34 +1797,43 @@ TEST(AnalyticsRecorderTest, // bandwidth_upgrade_attempts_) will stay there. ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - upgrade_attempt < + } + stop_reason: FINISH_SESSION_STOP_ADVERTISING + } + upgrade_attempt { direction: INCOMING from_medium: BLE to_medium: WIFI_LAN upgrade_result: WIFI_LAN_MEDIUM_ERROR error_stage: WIFI_LAN_SOCKET_CREATION connection_token: "connection_token" - > - upgrade_attempt < + operation_result { + result_category: CATEGORY_CONNECTIVITY_ERROR + result_code: CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL + } + } + upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH to_medium: WIFI_LAN upgrade_result: UPGRADE_RESULT_SUCCESS error_stage: UPGRADE_SUCCESS connection_token: "connection_token" - > + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH @@ -1533,10 +1841,14 @@ TEST(AnalyticsRecorderTest, upgrade_result: UNFINISHED_ERROR error_stage: UPGRADE_UNFINISHED connection_token: "connection_token" + operation_result { + result_category: CATEGORY_DEVICE_STATE_ERROR + result_code: DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS + } } - >)pb"); + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1554,43 +1866,51 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + } + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - upgrade_attempt < + } + } + upgrade_attempt { direction: INCOMING from_medium: BLE to_medium: WIFI_LAN upgrade_result: WIFI_LAN_MEDIUM_ERROR error_stage: WIFI_LAN_SOCKET_CREATION connection_token: "connection_token" - > - upgrade_attempt < + operation_result { + result_category: CATEGORY_CONNECTIVITY_ERROR + result_code: CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL + } + } + upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH to_medium: WIFI_LAN upgrade_result: UPGRADE_RESULT_SUCCESS error_stage: UPGRADE_SUCCESS connection_token: "connection_token" - > + operation_result { + result_category: CATEGORY_SUCCESS + result_code: DETAIL_SUCCESS + } + } upgrade_attempt { direction: INCOMING from_medium: BLUETOOTH @@ -1598,10 +1918,14 @@ TEST(AnalyticsRecorderTest, upgrade_result: UNFINISHED_ERROR error_stage: UPGRADE_UNFINISHED connection_token: "connection_token" + operation_result { + result_category: CATEGORY_DEVICE_STATE_ERROR + result_code: DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS + } } - >)pb"); + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } // Test if current_strategy_ is reset by checking if the same strategy would @@ -1613,18 +1937,22 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLUETOOTH}); + /*mediums=*/{BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); // LogSession analytics_recorder.LogSession(); ASSERT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result()); - //// The same strategy session shouldn't be logged again with the same client - //// session. + // The same strategy session shouldn't be logged again with the same client + // session. EXPECT_THAT(event_logger.GetLoggedEventTypes(), Contains(START_STRATEGY_SESSION).Times(1)); @@ -1639,7 +1967,9 @@ TEST(AnalyticsRecorderTest, // LogSession again CountDownLatch new_client_session_done_latch(1); event_logger.SetClientSessionDoneLatch(new_client_session_done_latch); - analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLUETOOTH}); + + analytics_recorder.OnStartAdvertising(strategy, /*mediums=*/{BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); analytics_recorder.LogSession(); @@ -1655,12 +1985,16 @@ TEST(AnalyticsRecorderTest, NotLogSameStrategySessionProtoAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); - //// Via OnStartAdvertising, current_strategy_session_is set in - //// UpdateStrategySessionLocked. + // Via OnStartAdvertising, current_strategy_session_is set in + // UpdateStrategySessionLocked. + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); // LogSession @@ -1669,22 +2003,23 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + stop_reason: CLIENT_STOP_ADVERTISING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1695,15 +2030,15 @@ TEST(AnalyticsRecorderTest, new_start_client_session_done_latch.Await(kDefaultTimeout).result()); // LogSession again - // - if current_strategy_session_ is reset, the same strategy_session_proto - // will be logged. + // - if current_strategy_session_ is reset, the same + // strategy_session_proto will be logged. CountDownLatch new_client_session_done_latch(1); event_logger.SetClientSessionDoneLatch(new_client_session_done_latch); analytics_recorder.LogSession(); ASSERT_TRUE(new_client_session_done_latch.Await(kDefaultTimeout).result()); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto)))); + Not(EqualsProto(strategy_session_proto))); } // Test if current_advertising_phase_ is reset. @@ -1711,11 +2046,15 @@ TEST(AnalyticsRecorderTest, NotLogDuplicateAdvertisingPhaseAfterSessionWasLogged) { CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising( connections::Strategy::kP2pStar, - /*mediums=*/{BLUETOOTH}); // set current_advertising_phase_ + /*mediums=*/{BLUETOOTH}, + advertising_metadata_params.get()); // set current_advertising_phase_ analytics_recorder.OnStopAdvertising(); // LogSession @@ -1724,21 +2063,22 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + stop_reason: CLIENT_STOP_ADVERTISING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1759,28 +2099,28 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - advertising_phase < + } + } + advertising_phase { medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } // Test if current_discovery_phase_ is reset. @@ -1790,12 +2130,16 @@ TEST(AnalyticsRecorderTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); + auto discovery_metadata_params = + analytics_recorder.BuildDiscoveryMetadataParams( + /*is_extended_advertisement_supported*/ true, + /*connected_ap_frequency*/ 1, /*is_nfc_available=*/false); analytics_recorder.OnStartDiscovery( - strategy, {BLUETOOTH}, /*is_extended_advertisement_supported=*/true, - /*connected_ap_frequency=*/1, - /*is_nfc_available=*/false); // set current_discovery_phase_ + strategy, {BLUETOOTH}, + discovery_metadata_params.get()); // set current_discovery_phase_ analytics_recorder.OnStopDiscovery(); analytics_recorder.OnEndpointFound(BLUETOOTH); @@ -1805,21 +2149,23 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto1 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLUETOOTH - discovery_metadata < + discovered_endpoint { medium: BLUETOOTH } + discovery_metadata { supports_extended_ble_advertisements: true connected_ap_frequency: 1 supports_nfc_technology: false - > - > - >)pb"); + } + stop_reason: CLIENT_STOP_DISCOVERING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto1))); + EqualsProto(strategy_session_proto1)); // LogStartSession CountDownLatch new_start_client_session_done_latch(1); @@ -1840,28 +2186,30 @@ TEST(AnalyticsRecorderTest, ConnectionsLog::ClientSession strategy_session_proto2 = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: DISCOVERER - discovery_phase < + discovery_phase { medium: BLUETOOTH - discovery_metadata < + discovered_endpoint { medium: BLUETOOTH } + discovery_metadata { supports_extended_ble_advertisements: true connected_ap_frequency: 1 supports_nfc_technology: false - > - > - discovery_phase < + } + stop_reason: CLIENT_STOP_DISCOVERING + } + discovery_phase { medium: BLUETOOTH - discovery_metadata < + discovery_metadata { supports_extended_ble_advertisements: true connected_ap_frequency: 1 supports_nfc_technology: false - > - > - >)pb"); + } + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Not(Partially(EqualsProto(strategy_session_proto2)))); + Not(EqualsProto(strategy_session_proto2))); } TEST(AnalyticsRecorderOnConnectionClosedTest, @@ -1870,12 +2218,16 @@ TEST(AnalyticsRecorderOnConnectionClosedTest, CountDownLatch client_session_done_latch(1); FakeEventLogger event_logger(client_session_done_latch); - AnalyticsRecorder analytics_recorder(&event_logger); + AnalyticsRecorder analytics_recorder(&event_logger, + /*no_record_time_millis=*/true); // via OnStartAdvertising, current_strategy_session_ is set in // UpdateStrategySessionLocked. + auto advertising_metadata_params = + analytics_recorder.BuildAdvertisingMetadataParams(); analytics_recorder.OnStartAdvertising(connections::Strategy::kP2pStar, - /*mediums=*/{BLE, BLUETOOTH}); + /*mediums=*/{BLE, BLUETOOTH}, + advertising_metadata_params.get()); analytics_recorder.OnStopAdvertising(); // LogSession @@ -1884,22 +2236,23 @@ TEST(AnalyticsRecorderOnConnectionClosedTest, ConnectionsLog::ClientSession strategy_session_proto = ParseTextProtoOrDie(R"pb( - strategy_session < + strategy_session { strategy: P2P_STAR role: ADVERTISER - advertising_phase < + advertising_phase { medium: BLE medium: BLUETOOTH - advertising_metadata < + advertising_metadata { supports_extended_ble_advertisements: false connected_ap_frequency: 0 supports_nfc_technology: false - > - > - >)pb"); + } + stop_reason: CLIENT_STOP_ADVERTISING + } + })pb"); EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); // Without calling OnStartAdvertising won't create new // current_strategy_session_. @@ -1913,7 +2266,7 @@ TEST(AnalyticsRecorderOnConnectionClosedTest, // The proto won't change. EXPECT_THAT(event_logger.GetLoggedClientSession(), - Partially(EqualsProto(strategy_session_proto))); + EqualsProto(strategy_session_proto)); } } // namespace diff --git a/connections/implementation/analytics/connection_attempt_metadata_params.h b/connections/implementation/analytics/connection_attempt_metadata_params.h index 65af75ab18..980c033084 100644 --- a/connections/implementation/analytics/connection_attempt_metadata_params.h +++ b/connections/implementation/analytics/connection_attempt_metadata_params.h @@ -37,6 +37,9 @@ struct ConnectionAttemptMetadataParams { int max_wifi_tx_speed = 0; int max_wifi_rx_speed = 0; int channel_width = -1; // -1 as Unknown. + location::nearby::proto::connections::OperationResultCode + operation_result_code = location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN; }; } // namespace nearby diff --git a/connections/implementation/analytics/discovery_metadata_params.h b/connections/implementation/analytics/discovery_metadata_params.h new file mode 100644 index 0000000000..6442b03c1d --- /dev/null +++ b/connections/implementation/analytics/discovery_metadata_params.h @@ -0,0 +1,36 @@ +// Copyright 2024 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_DISCOVERY_METADATA_PARAMS_H_ +#define ANALYTICS_DISCOVERY_METADATA_PARAMS_H_ + +#include + +#include "internal/proto/analytics/connections_log.pb.h" + +namespace nearby { + +// A struct to construct DiscoveryMetadata for the analytics recorder. +struct DiscoveryMetadataParams { + bool is_extended_advertisement_supported = false; + int connected_ap_frequency = 0; + bool is_nfc_available = false; + std::vector + operation_result_with_mediums = {}; +}; + +} // namespace nearby + +#endif // ANALYTICS_DISCOVERY_METADATA_PARAMS_H_ diff --git a/connections/implementation/base_bwu_handler_test.cc b/connections/implementation/base_bwu_handler_test.cc index 13fe331b2c..b87c8d5bf7 100644 --- a/connections/implementation/base_bwu_handler_test.cc +++ b/connections/implementation/base_bwu_handler_test.cc @@ -14,18 +14,27 @@ #include "connections/implementation/base_bwu_handler.h" +#include +#include #include +#include #include "gtest/gtest.h" #include "absl/strings/string_view.h" +#include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" #include "connections/implementation/service_id_constants.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { namespace { -// Because BaseBwuHandler is still an abstract class, we need to implement the -// pure virtual functions in order to test BaseBwuHandler's bookkeeping logic. +using ::location::nearby::proto::connections::OperationResultCode; + +// Because BaseBwuHandler is still an abstract class, we need to implement the +// pure virtual functions in order to test BaseBwuHandler's bookkeeping logic. class BwuHandlerImpl : public BaseBwuHandler { public: using Medium = ::location::nearby::proto::connections::Medium; @@ -34,8 +43,8 @@ class BwuHandlerImpl : public BaseBwuHandler { // for every method. struct InputData { ClientProxy* client = nullptr; - absl::optional service_id; - absl::optional endpoint_id; + std::optional service_id; + std::optional endpoint_id; }; BwuHandlerImpl() : BaseBwuHandler(nullptr) {} @@ -52,11 +61,12 @@ class BwuHandlerImpl : public BaseBwuHandler { private: // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( + ErrorOr> + CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) final { - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } Medium GetUpgradeMedium() const final { return Medium::UNKNOWN_MEDIUM; } void OnEndpointDisconnect(ClientProxy* client, diff --git a/connections/implementation/base_pcp_handler.cc b/connections/implementation/base_pcp_handler.cc index 6c1553069f..e6e14d1d43 100644 --- a/connections/implementation/base_pcp_handler.cc +++ b/connections/implementation/base_pcp_handler.cc @@ -85,7 +85,6 @@ namespace nearby { namespace connections { namespace { - constexpr int kEndpointCancelAlarmTimeout = 10; std::string AuthenticationStatusToString(nearby::AuthenticationStatus status) { @@ -98,9 +97,9 @@ 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; @@ -108,11 +107,9 @@ using ::location::nearby::connections::MediumMetadata; using ::location::nearby::connections::OfflineFrame; using ::location::nearby::connections::PresenceDevice; using ::location::nearby::connections::V1Frame; +using ::location::nearby::proto::connections::OperationResultCode; using ::securegcm::UKey2Handshake; -constexpr absl::Duration BasePcpHandler::kConnectionRequestReadTimeout; -constexpr absl::Duration BasePcpHandler::kRejectedConnectionCloseDelay; - BasePcpHandler::BasePcpHandler(Mediums* mediums, EndpointManager* endpoint_manager, EndpointChannelManager* channel_manager, @@ -271,9 +268,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), - compatible_advertising_options); + client->StartedAdvertising( + service_id, GetStrategy(), info.listener, + absl::MakeSpan(result.mediums), + std::move(result.operation_result_with_mediums), + compatible_advertising_options); client->UpdateLocalEndpointInfo(info.endpoint_info.string_data()); response.Set({Status::kSuccess}); }); @@ -455,7 +454,9 @@ Status BasePcpHandler::StartDiscovery(ClientProxy* client, } client->StartedDiscovery( service_id, GetStrategy(), std::move(listener), - absl::MakeSpan(result.mediums), stripped_discovery_options); + absl::MakeSpan(result.mediums), + std::move(result.operation_result_with_mediums), + stripped_discovery_options); response.Set({Status::kSuccess}); }); return WaitForResult(absl::StrCat("StartDiscovery(", service_id, ")"), @@ -623,7 +624,9 @@ void BasePcpHandler::OnEncryptionSuccessRunnableV3( connection_info.client, connection_info.medium, remote_device.GetEndpointId(), connection_info.channel.get(), connection_info.is_incoming, connection_info.start_time, - {Status::kEndpointIoError}, connection_info.result.lock().get()); + {Status::kEndpointIoError}, + OperationResultCode::NEARBY_AUTHENTICATION_FAILURE, + connection_info.result.lock().get()); return; } @@ -685,6 +688,7 @@ void BasePcpHandler::OnEncryptionSuccessRunnable( connection_info.client, connection_info.medium, endpoint_id, connection_info.channel.get(), connection_info.is_incoming, connection_info.start_time, {Status::kEndpointIoError}, + OperationResultCode::NEARBY_AUTHENTICATION_FAILURE, connection_info.result.lock().get()); return; } @@ -763,7 +767,7 @@ void BasePcpHandler::OnEncryptionFailureRunnable( ProcessPreConnectionInitiationFailure( info.client, info.medium, endpoint_id, info.channel.get(), info.is_incoming, info.start_time, {Status::kEndpointIoError}, - info.result.lock().get()); + OperationResultCode::NEARBY_ENCRYPTION_FAILURE, info.result.lock().get()); } ConnectionInfo BasePcpHandler::FillConnectionInfo( @@ -862,7 +866,7 @@ Status BasePcpHandler::RequestConnection( ProcessPreConnectionInitiationFailure( client, channel_medium, endpoint_id, channel.get(), /* is_incoming = */ false, start_time, connect_impl_result.status, - result.get()); + connect_impl_result.operation_result_code, result.get()); return; } @@ -878,13 +882,14 @@ Status BasePcpHandler::RequestConnection( Exception write_exception = WriteConnectionRequestFrame( local_device->GetType(), local_device->ToProtoBytes(), connection_info, channel.get()); - if (!write_exception.Ok()) { NEARBY_LOGS(INFO) << "Failed to send connection request: endpoint_id=" << endpoint_id; ProcessPreConnectionInitiationFailure( client, channel_medium, endpoint_id, channel.get(), /* is_incoming = */ false, start_time, {Status::kEndpointIoError}, + client->GetAnalyticsRecorder() + .GetChannelIoErrorResultCodeFromMedium(channel_medium), result.get()); return; } @@ -1005,7 +1010,7 @@ Status BasePcpHandler::RequestConnectionV3( ProcessPreConnectionInitiationFailure( client, channel_medium, endpoint_id, channel.get(), /* is_incoming = */ false, start_time, connect_impl_result.status, - result.get()); + connect_impl_result.operation_result_code, result.get()); return; } @@ -1031,6 +1036,8 @@ Status BasePcpHandler::RequestConnectionV3( ProcessPreConnectionInitiationFailure( client, channel_medium, endpoint_id, channel.get(), /* is_incoming = */ false, start_time, {Status::kEndpointIoError}, + client->GetAnalyticsRecorder() + .GetChannelIoErrorResultCodeFromMedium(channel_medium), result.get()); return; } @@ -1140,6 +1147,26 @@ void BasePcpHandler::StripOutUnavailableMediums( } } +std::unique_ptr +BasePcpHandler::GetOperationResultWithMediumByResultCode( + ClientProxy* client, location::nearby::proto::connections::Medium medium, + int update_index, + location::nearby::proto::connections::OperationResultCode + operation_result_code, + location::nearby::proto::connections::ConnectionMode connection_mode) { + auto operation_result_with_medium = + std::make_unique(); + operation_result_with_medium->set_medium(medium); + operation_result_with_medium->set_result_code(operation_result_code); + operation_result_with_medium->set_result_category( + client->GetAnalyticsRecorder().GetOperationResultCateory( + operation_result_code)); + operation_result_with_medium->set_connection_mode(connection_mode); + operation_result_with_medium->set_update_index(update_index); + + return operation_result_with_medium; +} + void BasePcpHandler::StripOutUnavailableMediums( DiscoveryOptions& discovery_options) { BooleanMediumSelector& allowed = discovery_options.allowed; @@ -1338,7 +1365,8 @@ Exception BasePcpHandler::WriteConnectionRequestFrame( void BasePcpHandler::ProcessPreConnectionInitiationFailure( ClientProxy* client, Medium medium, const std::string& endpoint_id, EndpointChannel* channel, bool is_incoming, absl::Time start_time, - Status status, Future* result) { + Status status, OperationResultCode operation_result_code, + Future* result) { if (channel != nullptr) { channel->Close(); } @@ -1349,7 +1377,7 @@ void BasePcpHandler::ProcessPreConnectionInitiationFailure( } LogConnectionAttemptFailure(client, medium, endpoint_id, is_incoming, - start_time, channel); + start_time, channel, operation_result_code); // result is hold inside a swapper, and saved in PendingConnectionInfo. // PendingConnectionInfo destructor will clear the memory of SettableFuture // shared_ptr for result. @@ -1850,7 +1878,10 @@ Exception BasePcpHandler::OnIncomingConnection( << "with error: " << wrapped_frame.exception(); ProcessPreConnectionInitiationFailure( client, medium, /*endpoint_id=*/"", channel.get(), - /*is_incoming=*/true, start_time, {Status::kError}, nullptr); + /*is_incoming=*/true, start_time, {Status::kError}, + client->GetAnalyticsRecorder().GetChannelIoErrorResultCodeFromMedium( + medium), + nullptr); } return wrapped_frame.GetException(); } @@ -2081,7 +2112,9 @@ void BasePcpHandler::ProcessTieBreakLoss( BasePcpHandler::PendingConnectionInfo* info) { ProcessPreConnectionInitiationFailure( client, info->medium, endpoint_id, info->channel.get(), info->is_incoming, - info->start_time, {Status::kEndpointIoError}, info->result.lock().get()); + info->start_time, {Status::kEndpointIoError}, + OperationResultCode::CLIENT_PROCESS_TIE_BREAK_LOSS, + info->result.lock().get()); ProcessPreConnectionResultFailure(client, endpoint_id, /* should_call_disconnect_endpoint= */ true, DisconnectionReason::IO_ERROR); @@ -2348,8 +2381,8 @@ std::string BasePcpHandler::GetHashedConnectionToken( void BasePcpHandler::LogConnectionAttemptFailure( ClientProxy* client, Medium medium, const std::string& endpoint_id, - bool is_incoming, absl::Time start_time, - EndpointChannel* endpoint_channel) { + bool is_incoming, absl::Time start_time, EndpointChannel* endpoint_channel, + OperationResultCode operation_result_code) { location::nearby::proto::connections::ConnectionAttemptResult result = Cancelled(client, endpoint_id) ? location::nearby::proto::connections::RESULT_CANCELLED @@ -2361,6 +2394,8 @@ void BasePcpHandler::LogConnectionAttemptFailure( client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( endpoint_channel->GetTechnology(), endpoint_channel->GetBand(), endpoint_channel->GetFrequency(), endpoint_channel->GetTryCount()); + connections_attempt_metadata_params->operation_result_code = + operation_result_code; } if (is_incoming) { client->GetAnalyticsRecorder().OnIncomingConnectionAttempt( @@ -2388,6 +2423,8 @@ void BasePcpHandler::LogConnectionAttemptSuccess( connection_info.channel->GetBand(), connection_info.channel->GetFrequency(), connection_info.channel->GetTryCount()); + connections_attempt_metadata_params->operation_result_code = + OperationResultCode::DETAIL_SUCCESS; } else { NEARBY_LOGS(ERROR) << "PendingConnectionInfo channel is null for " "LogConnectionAttemptSuccess. Bail out."; diff --git a/connections/implementation/base_pcp_handler.h b/connections/implementation/base_pcp_handler.h index 042b87683d..9541157927 100644 --- a/connections/implementation/base_pcp_handler.h +++ b/connections/implementation/base_pcp_handler.h @@ -195,6 +195,9 @@ class BasePcpHandler : public PcpHandler, // If success, the mediums on which we are now advertising/discovering, for // analytics. std::vector mediums; + std::vector + operation_result_with_mediums; }; // Represents an endpoint that we've discovered. Typically, the implementation @@ -274,6 +277,9 @@ class BasePcpHandler : public PcpHandler, location::nearby::proto::connections::Medium medium = location::nearby::proto::connections::Medium::UNKNOWN_MEDIUM; Status status = {Status::kError}; + location::nearby::proto::connections::OperationResultCode + operation_result_code = location::nearby::proto::connections:: + OperationResultCode::DETAIL_UNKNOWN; std::unique_ptr endpoint_channel; }; @@ -412,6 +418,16 @@ class BasePcpHandler : public PcpHandler, void StripOutWifiHotspotMedium(ConnectionInfo& connection_info); + std::unique_ptr + GetOperationResultWithMediumByResultCode( + ClientProxy* client, location::nearby::proto::connections::Medium medium, + int update_index, + location::nearby::proto::connections::OperationResultCode + operation_result_code, + location::nearby::proto::connections::ConnectionMode connection_mode = + location::nearby::proto::connections::ConnectionMode::LEGACY); + // Test only. int GetEndpointLostByMediumAlarmsCount() RUN_ON_PCP_HANDLER_THREAD() { return endpoint_lost_by_medium_alarms_.size(); @@ -567,7 +583,10 @@ class BasePcpHandler : public PcpHandler, void ProcessPreConnectionInitiationFailure( ClientProxy* client, Medium medium, const std::string& endpoint_id, EndpointChannel* channel, bool is_incoming, absl::Time start_time, - Status status, Future* result); + Status status, + location::nearby::proto::connections::OperationResultCode + operation_result_code, + Future* result); void ProcessPreConnectionResultFailure(ClientProxy* client, const std::string& endpoint_id, bool should_call_disconnect_endpoint, @@ -593,11 +612,12 @@ class BasePcpHandler : public PcpHandler, // array. std::string GetHashedConnectionToken(const ByteArray& token_bytes); - static void LogConnectionAttemptFailure(ClientProxy* client, Medium medium, - const std::string& endpoint_id, - bool is_incoming, - absl::Time start_time, - EndpointChannel* endpoint_channel); + static void LogConnectionAttemptFailure( + ClientProxy* client, Medium medium, const std::string& endpoint_id, + bool is_incoming, absl::Time start_time, + EndpointChannel* endpoint_channel, + location::nearby::proto::connections::OperationResultCode + operation_result_code); static void LogConnectionAttemptSuccess( const std::string& endpoint_id, diff --git a/connections/implementation/bluetooth_bwu_handler.cc b/connections/implementation/bluetooth_bwu_handler.cc index 74e723125e..62ef276509 100644 --- a/connections/implementation/bluetooth_bwu_handler.cc +++ b/connections/implementation/bluetooth_bwu_handler.cc @@ -14,13 +14,21 @@ #include "connections/implementation/bluetooth_bwu_handler.h" +#include #include #include #include "absl/functional/bind_front.h" +#include "connections/implementation/base_bwu_handler.h" #include "connections/implementation/bluetooth_endpoint_channel.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/mediums.h" #include "connections/implementation/offline_frames.h" +#include "internal/platform/bluetooth_adapter.h" +#include "internal/platform/bluetooth_classic.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" // Manages the Bluetooth-specific methods needed to upgrade an {@link @@ -29,6 +37,10 @@ namespace nearby { namespace connections { +namespace { +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace + BluetoothBwuHandler::BluetoothBwuHandler( Mediums& mediums, IncomingConnectionCallback incoming_connection_callback) : BaseBwuHandler(std::move(incoming_connection_callback)), @@ -37,7 +49,7 @@ BluetoothBwuHandler::BluetoothBwuHandler( // Called by BWU target. Retrieves a new medium info from incoming message, // and establishes connection over BT using this info. // Returns a channel ready to exchange data or nullptr on error. -std::unique_ptr +ErrorOr> BluetoothBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { @@ -47,7 +59,8 @@ BluetoothBwuHandler::CreateUpgradedEndpointChannel( !bluetooth_credentials.has_mac_address()) { NEARBY_LOGS(ERROR) << "BluetoothBwuHandler failed to parse UpgradePathInfo."; - return nullptr; + return { + Error(OperationResultCode::CONNECTIVITY_BLUETOOTH_INVALID_CREDENTIAL)}; } const std::string& service_name = bluetooth_credentials.service_name(); @@ -64,17 +77,18 @@ BluetoothBwuHandler::CreateUpgradedEndpointChannel( << "BluetoothBwuHandler failed to derive a valid Bluetooth device " "from the MAC address (" << mac_address << ") for endpoint " << endpoint_id; - return nullptr; + return {Error( + OperationResultCode::CONNECTIVITY_BLUETOOTH_DEVICE_OBTAIN_FAILURE)}; } - BluetoothSocket socket = bluetooth_medium_.Connect( + ErrorOr socket_result = bluetooth_medium_.Connect( device, service_id, client->GetCancellationFlag(endpoint_id)); - if (!socket.IsValid()) { + if (socket_result.has_error()) { NEARBY_LOGS(ERROR) << "BluetoothBwuHandler failed to connect to the Bluetooth device (" << service_name << ", " << mac_address << ") for endpoint " << endpoint_id << " and service ID " << service_id; - return nullptr; + return {Error(socket_result.error().operation_result_code().value())}; } NEARBY_VLOG(1) @@ -83,19 +97,20 @@ BluetoothBwuHandler::CreateUpgradedEndpointChannel( << endpoint_id; auto channel = std::make_unique( - service_id, /*channel_name=*/service_id, socket); + service_id, /*channel_name=*/service_id, socket_result.value()); if (channel == nullptr) { NEARBY_LOGS(ERROR) << "BluetoothBwuHandler failed to create Bluetooth endpoint " "channel to the Bluetooth device (" << service_name << ", " << mac_address << ") for endpoint " << endpoint_id << " and service ID " << service_id; - socket.Close(); - return nullptr; + socket_result.value().Close(); + return {Error( + OperationResultCode::NEARBY_BT_ENDPOINT_CHANNEL_CREATION_FAILURE)}; } client->SetBluetoothMacAddress(endpoint_id, mac_address); - return channel; + return {std::move(channel)}; } ByteArray BluetoothBwuHandler::HandleInitializeUpgradedMediumForEndpoint( @@ -146,7 +161,7 @@ void BluetoothBwuHandler::HandleRevertInitiatorStateForService( void BluetoothBwuHandler::OnIncomingBluetoothConnection( ClientProxy* client, const std::string& upgrade_service_id, BluetoothSocket socket) { - auto channel = absl::make_unique( + auto channel = std::make_unique( upgrade_service_id, /*channel_name=*/upgrade_service_id, socket); std::unique_ptr connection{ new IncomingSocketConnection{ diff --git a/connections/implementation/bluetooth_bwu_handler.h b/connections/implementation/bluetooth_bwu_handler.h index 6563eebf8f..46466ee24b 100644 --- a/connections/implementation/bluetooth_bwu_handler.h +++ b/connections/implementation/bluetooth_bwu_handler.h @@ -15,14 +15,20 @@ #ifndef CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_ #define CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_ +#include #include +#include #include "connections/implementation/base_bwu_handler.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/bluetooth_classic.h" +#include "connections/implementation/mediums/bluetooth_radio.h" #include "connections/implementation/mediums/mediums.h" -#include "connections/implementation/mediums/utils.h" +#include "connections/medium_selector.h" #include "internal/platform/bluetooth_classic.h" -#include "internal/platform/count_down_latch.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -51,10 +57,11 @@ class BluetoothBwuHandler : public BaseBwuHandler { }; // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; Medium GetUpgradeMedium() const final { return Medium::BLUETOOTH; } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {} diff --git a/connections/implementation/bluetooth_bwu_test.cc b/connections/implementation/bluetooth_bwu_test.cc index 6b0b989740..e6a71b6cc8 100644 --- a/connections/implementation/bluetooth_bwu_test.cc +++ b/connections/implementation/bluetooth_bwu_test.cc @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include "gtest/gtest.h" #include "absl/time/time.h" @@ -25,6 +26,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/count_down_latch.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" @@ -35,6 +37,7 @@ namespace connections { namespace { using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::proto::connections::OperationResultCode; constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); } // namespace @@ -101,17 +104,23 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) { auto bwu_frame = upgrade_frame.result().v1().bandwidth_upgrade_negotiation(); - std::unique_ptr new_channel = + ErrorOr> result = handler_2->CreateUpgradedEndpointChannel(&client_2, /*service_id=*/"A", /*endpoint_id=*/"1", bwu_frame.upgrade_path_info()); if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { + ASSERT_TRUE(result.has_value()); + std::unique_ptr new_channel = std::move(result.value()); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_EQ(new_channel->GetMedium(), location::nearby::proto::connections::Medium::BLUETOOTH); } else { + EXPECT_FALSE(result.has_value()); + EXPECT_TRUE(result.has_error()); + EXPECT_EQ( + result.error().operation_result_code(), + OperationResultCode::CONNECTIVITY_BLUETOOTH_DEVICE_OBTAIN_FAILURE); accept_latch.CountDown(); - EXPECT_EQ(new_channel, nullptr); } EXPECT_FALSE(mediums_2.GetBluetoothClassic().GetMacAddress().empty()); handler_2->RevertResponderState(/*service_id=*/"A"); diff --git a/connections/implementation/bwu_handler.h b/connections/implementation/bwu_handler.h index de1ee7e04d..0deb84bc7c 100644 --- a/connections/implementation/bwu_handler.h +++ b/connections/implementation/bwu_handler.h @@ -15,14 +15,15 @@ #ifndef CORE_INTERNAL_BWU_HANDLER_H_ #define CORE_INTERNAL_BWU_HANDLER_H_ -#include +#include #include #include "absl/functional/any_invocable.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/offline_frames.h" -#include "internal/platform/count_down_latch.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -81,14 +82,16 @@ class BwuHandler { // that hasn't already been done) using the UpgradePathInfo sent by the // Initiator, and returns a new EndpointChannel for the upgraded medium. // @BwuHandlerThread - virtual std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) = 0; + virtual ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) = 0; // Returns the upgrade medium of the BwuHandler. // @BwuHandlerThread - virtual Medium GetUpgradeMedium() const = 0; + virtual location::nearby::proto::connections::Medium GetUpgradeMedium() + const = 0; virtual void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) = 0; diff --git a/connections/implementation/bwu_manager.cc b/connections/implementation/bwu_manager.cc index 28f37f2cef..e5a80b7410 100644 --- a/connections/implementation/bwu_manager.cc +++ b/connections/implementation/bwu_manager.cc @@ -31,6 +31,7 @@ #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" +#include "connections/implementation/mediums/mediums.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/service_id_constants.h" #ifdef NO_WEBRTC @@ -45,6 +46,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancelable_alarm.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/system_clock.h" #include "internal/platform/logging.h" @@ -54,13 +56,17 @@ namespace nearby { namespace connections { +namespace { using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame; using ::location::nearby::connections::OfflineFrame; using ::location::nearby::connections::V1Frame; +using ::location::nearby::proto::connections::BandwidthUpgradeErrorStage; +using ::location::nearby::proto::connections::BandwidthUpgradeResult; +using ::location::nearby::proto::connections::ConnectionAttemptResult; +using ::location::nearby::proto::connections::ConnectionAttemptType; using ::location::nearby::proto::connections::DisconnectionReason; - -// Required for C++ 14 support in Chrome -constexpr absl::Duration BwuManager::kReadClientIntroductionFrameTimeout; +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace BwuManager::BwuManager( Mediums& mediums, EndpointManager& endpoint_manager, @@ -258,8 +264,9 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, << endpoint_id << " because it couldn't find an existing EndpointChannel for it."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::CHANNEL_ERROR, - location::nearby::proto::connections::NETWORK_AVAILABLE); + endpoint_id, BandwidthUpgradeResult::CHANNEL_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + OperationResultCode::NEARBY_GENERIC_OLD_ENDPOINT_CHANNEL_NULL); return; } @@ -277,6 +284,10 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, << " because it is already connected over medium " << location::nearby::proto::connections::Medium_Name( proposed_medium); + client->GetAnalyticsRecorder().OnBandwidthUpgradeError( + endpoint_id, BandwidthUpgradeResult::ALREADY_ON_MEDIUM_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + OperationResultCode::MEDIUM_UNAVAILABLE_UPGRADE_ON_SAME_MEDIUM); return; } @@ -296,10 +307,16 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, UpgradePathInfo info; info.set_medium(parser::MediumToUpgradePathInfoMedium(proposed_medium)); - ProcessUpgradeFailureEvent(client, endpoint_id, info); + ProcessUpgradeFailureEvent( + client, endpoint_id, info, + BandwidthUpgradeResult::REMOTE_CONNECTION_ERROR, + /*record_analytic=*/false, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR); + client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::NETWORK_AVAILABLE); + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR); return; } if (!channel->Write(bytes).Ok()) { @@ -503,8 +520,11 @@ void BwuManager::OnBwuNegotiationFrame(ClientProxy* client, frame.upgrade_path_info()); break; case BwuNegotiationFrame::UPGRADE_FAILURE: - ProcessUpgradeFailureEvent(client, endpoint_id, - frame.upgrade_path_info()); + ProcessUpgradeFailureEvent( + client, endpoint_id, frame.upgrade_path_info(), + BandwidthUpgradeResult::REMOTE_CONNECTION_ERROR, + /* record_analytic= */ true, + OperationResultCode::NEARBY_GENERIC_REMOTE_UPGRADE_FAILURE); break; case BwuNegotiationFrame::LAST_WRITE_TO_PRIOR_CHANNEL: ProcessLastWriteToPriorChannelEvent(client, endpoint_id); @@ -539,7 +559,8 @@ void BwuManager::OnIncomingConnection( connection->socket->Close(); AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( location::nearby::proto::connections::MEDIUM_ERROR, - location::nearby::proto::connections::SOCKET_CREATION); + BandwidthUpgradeErrorStage::SOCKET_CREATION, + OperationResultCode::NEARBY_GENERIC_NEW_ENDPOINT_CHANNEL_NULL); return; } @@ -603,6 +624,8 @@ void BwuManager::OnIncomingConnection( client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( channel->GetTechnology(), channel->GetBand(), channel->GetFrequency(), channel->GetTryCount()); + connections_attempt_metadata_params->operation_result_code = + OperationResultCode::DETAIL_SUCCESS; } client->GetAnalyticsRecorder().OnIncomingConnectionAttempt( location::nearby::proto::connections::UPGRADE, channel->GetMedium(), @@ -653,8 +676,9 @@ void BwuManager::RunUpgradeProtocol( << " when registering the new EndpointChannel, short-circuiting the " "upgrade protocol."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::CHANNEL_ERROR, - location::nearby::proto::connections::PRIOR_ENDPOINT_CHANNEL); + endpoint_id, BandwidthUpgradeResult::CHANNEL_ERROR, + BandwidthUpgradeErrorStage::PRIOR_ENDPOINT_CHANNEL, + OperationResultCode::NEARBY_GENERIC_OLD_ENDPOINT_CHANNEL_NULL); return; } channel_manager_->ReplaceChannelForEndpoint( @@ -670,8 +694,9 @@ void BwuManager::RunUpgradeProtocol( "endpoint " << endpoint_id << ", short-circuiting the upgrade protocol."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::LAST_WRITE_TO_PRIOR_CHANNEL); + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::LAST_WRITE_TO_PRIOR_CHANNEL, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR); return; } NEARBY_VLOG(1) << "BwuManager successfully wrote " @@ -770,10 +795,12 @@ void BwuManager::ProcessBwuPathAvailableEvent( client->GetConnectionToken(endpoint_id)); absl::Time connection_attempt_start_time = SystemClock::ElapsedRealtime(); - auto channel = ProcessBwuPathAvailableEventInternal(client, endpoint_id, - upgrade_path_info); - location::nearby::proto::connections::ConnectionAttemptResult - connection_attempt_result; + ErrorOr> result = + ProcessBwuPathAvailableEventInternal(client, endpoint_id, + upgrade_path_info); + std::unique_ptr channel = + result.has_value() ? std::move(result.value()) : nullptr; + ConnectionAttemptResult connection_attempt_result; if (channel != nullptr) { connection_attempt_result = location::nearby::proto::connections::RESULT_SUCCESS; @@ -781,27 +808,40 @@ void BwuManager::ProcessBwuPathAvailableEvent( connection_attempt_result = location::nearby::proto::connections::RESULT_CANCELLED; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_REMOTE_ERROR, - location::nearby::proto::connections::UPGRADE_CANCEL); + endpoint_id, BandwidthUpgradeResult::RESULT_REMOTE_ERROR, + BandwidthUpgradeErrorStage::UPGRADE_CANCEL, + OperationResultCode::CLIENT_CANCELLATION_UPGRADE_CANCELED_BY_REMOTE); } else { connection_attempt_result = location::nearby::proto::connections::RESULT_ERROR; } - std::unique_ptr - connections_attempt_metadata_params; if (channel != nullptr) { - connections_attempt_metadata_params = - client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( - channel->GetTechnology(), channel->GetBand(), - channel->GetFrequency(), channel->GetTryCount()); + std::unique_ptr + connections_attempt_metadata_params = + client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams( + channel->GetTechnology(), channel->GetBand(), + channel->GetFrequency(), channel->GetTryCount()); + connections_attempt_metadata_params->operation_result_code = + OperationResultCode::DETAIL_SUCCESS; + client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( + endpoint_id, ConnectionAttemptType::UPGRADE, upgrade_medium, + connection_attempt_result, + SystemClock::ElapsedRealtime() - connection_attempt_start_time, + client->GetConnectionToken(endpoint_id), + connections_attempt_metadata_params.get()); + } else { + auto connections_attempt_metadata_params = + std::make_unique(); + connections_attempt_metadata_params->operation_result_code = + result.error().operation_result_code().value(); + client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( + endpoint_id, ConnectionAttemptType::UPGRADE, upgrade_medium, + connection_attempt_result, + SystemClock::ElapsedRealtime() - connection_attempt_start_time, + client->GetConnectionToken(endpoint_id), + connections_attempt_metadata_params.get()); } - client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( - endpoint_id, location::nearby::proto::connections::UPGRADE, - upgrade_medium, connection_attempt_result, - SystemClock::ElapsedRealtime() - connection_attempt_start_time, - client->GetConnectionToken(endpoint_id), - connections_attempt_metadata_params.get()); if (channel == nullptr) { NEARBY_LOGS(INFO) << "Failed to get new channel."; @@ -814,9 +854,9 @@ void BwuManager::ProcessBwuPathAvailableEvent( !upgrade_path_info.supports_disabling_encryption()); } -std::unique_ptr +ErrorOr> BwuManager::ProcessBwuPathAvailableEventInternal( - ClientProxy* client, const string& endpoint_id, + ClientProxy* client, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { Medium medium = parser::UpgradePathInfoMediumToMedium(upgrade_path_info.medium()); @@ -826,7 +866,7 @@ BwuManager::ProcessBwuPathAvailableEventInternal( << endpoint_id << " medium " << location::nearby::proto::connections::Medium_Name(medium) << ". Upgrade medium not yet set for endpoint."; - return nullptr; + return {Error(OperationResultCode::NEARBY_UPGRADE_PATH_ON_WRONG_MEDIUM)}; } BwuHandler* handler = GetHandlerForMedium(medium); @@ -836,7 +876,7 @@ BwuManager::ProcessBwuPathAvailableEventInternal( << endpoint_id << " medium " << location::nearby::proto::connections::Medium_Name(medium) << ". No handler for medium."; - return nullptr; + return {Error(OperationResultCode::NEARBY_UPGRADE_PATH_ON_WRONG_MEDIUM)}; } NEARBY_LOGS(INFO) << "ProcessBwuPathAvailableEventInternal for " @@ -849,6 +889,8 @@ BwuManager::ProcessBwuPathAvailableEventInternal( // pointer in scope longer than necessary. std::string service_id; { + // TBD(edwinwu): Change return type to ErrorOr<> for GetChannelForEndpoint + // if possible. std::shared_ptr old_channel = channel_manager_->GetChannelForEndpoint(endpoint_id); if (!old_channel) { @@ -857,23 +899,26 @@ BwuManager::ProcessBwuPathAvailableEventInternal( << endpoint_id << " medium " << location::nearby::proto::connections::Medium_Name(medium) << ". Old endpoint channel is missing."; - return nullptr; + // TBD(edwinwu): Add a new operation result code for this. + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } service_id = old_channel->GetServiceId(); } - std::unique_ptr new_channel = + ErrorOr> result = handler->CreateUpgradedEndpointChannel(client, service_id, endpoint_id, upgrade_path_info); - if (!new_channel) { + if (result.has_error() || !result.has_value()) { NEARBY_LOGS(ERROR) << "BwuManager failed to create an endpoint " "channel to endpoint" << endpoint_id << ", aborting upgrade."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::SOCKET_CREATION); - return nullptr; + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::SOCKET_CREATION, + result.error().operation_result_code().value()); + return result; } + std::unique_ptr new_channel = std::move(result.value()); // Write the requisite BANDWIDTH_UPGRADE_NEGOTIATION.CLIENT_INTRODUCTION as // the first OfflineFrame on this new EndpointChannel. @@ -891,9 +936,13 @@ BwuManager::ProcessBwuPathAvailableEventInternal( "OfflineFrame to newly-created EndpointChannel " << new_channel->GetName() << ", aborting upgrade."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::CLIENT_INTRODUCTION); - return {}; + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::CLIENT_INTRODUCTION, + OperationResultCode:: + NEARBY_GENERIC_READ_CLIENT_INTRODUCTION_ACK_FORMAT_ERROR); + return { + Error(OperationResultCode:: + NEARBY_GENERIC_READ_CLIENT_INTRODUCTION_ACK_FORMAT_ERROR)}; } if (upgrade_path_info.supports_client_introduction_ack()) { @@ -906,8 +955,9 @@ BwuManager::ProcessBwuPathAvailableEventInternal( "BWU_NEGOTIATION.CLIENT_INTRODUCTION_ACK " "OfflineFrame to newly-created EndpointChannel " << new_channel->GetName() << ", aborting upgrade."; - - return {}; + return {Error( + OperationResultCode:: + NEARBY_GENERIC_READ_CLIENT_INTRODUCTION_ACK_FRAME_TYPE_ERROR)}; } } @@ -919,7 +969,7 @@ BwuManager::ProcessBwuPathAvailableEventInternal( // Set the AnalyticsRecorder so that the future closure of this // EndpointChannel will be recorded. - return new_channel; + return {std::move(new_channel)}; } void BwuManager::RunUpgradeFailedProtocol( @@ -942,8 +992,9 @@ void BwuManager::RunUpgradeFailedProtocol( << " when sending an upgrade failure frame, short-circuiting the " "upgrade protocol."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::CHANNEL_ERROR, - location::nearby::proto::connections::NETWORK_AVAILABLE); + endpoint_id, BandwidthUpgradeResult::CHANNEL_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + OperationResultCode::NEARBY_GENERIC_OLD_ENDPOINT_CHANNEL_NULL); return; } @@ -956,8 +1007,9 @@ void BwuManager::RunUpgradeFailedProtocol( "OfflineFrame to endpoint " << endpoint_id << ", short-circuiting the upgrade protocol."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::NETWORK_AVAILABLE); + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR); return; } @@ -1102,8 +1154,9 @@ void BwuManager::ProcessLastWriteToPriorChannelEvent( << endpoint_id << ", short-circuiting the upgrade protocol."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::RESULT_IO_ERROR, - location::nearby::proto::connections::SAFE_TO_CLOSE_PRIOR_CHANNEL); + endpoint_id, BandwidthUpgradeResult::RESULT_IO_ERROR, + BandwidthUpgradeErrorStage::SAFE_TO_CLOSE_PRIOR_CHANNEL, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR); return; } NEARBY_VLOG(1) << "BwuManager successfully wrote " @@ -1209,7 +1262,8 @@ void BwuManager::ProcessSafeToClosePriorChannelEvent( void BwuManager::ProcessUpgradeFailureEvent( ClientProxy* client, const std::string& endpoint_id, - const UpgradePathInfo& upgrade_info) { + const UpgradePathInfo& upgrade_info, BandwidthUpgradeResult result, + bool record_analytic, OperationResultCode operation_result_code) { NEARBY_LOGS(INFO) << "ProcessUpgradeFailureEvent for endpoint " << endpoint_id << " from medium: " << location::nearby::proto::connections::Medium_Name( @@ -1235,8 +1289,8 @@ void BwuManager::ProcessUpgradeFailureEvent( << " because we have other connected endpoints and can't try a new " "upgrade medium."; client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, location::nearby::proto::connections::CHANNEL_ERROR, - location::nearby::proto::connections::NETWORK_AVAILABLE); + endpoint_id, BandwidthUpgradeResult::CHANNEL_ERROR, + BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, operation_result_code); return; } @@ -1252,6 +1306,12 @@ void BwuManager::ProcessUpgradeFailureEvent( RevertBwuMediumForEndpoint(upgrade_service_id, endpoint_id); } + if (record_analytic) { + client->GetAnalyticsRecorder().OnBandwidthUpgradeError( + endpoint_id, result, BandwidthUpgradeErrorStage::NETWORK_AVAILABLE, + operation_result_code); + } + // Loop through the ordered list of upgrade mediums. One by one, remove the // top element until we get to the medium we last attempted to upgrade to. The // remainder of the list will contain the mediums we haven't attempted yet. @@ -1429,9 +1489,8 @@ void BwuManager::RetryUpgradesAfterDelay(ClientProxy* client, } void BwuManager::AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( - location::nearby::proto::connections::BandwidthUpgradeResult result, - location::nearby::proto::connections::BandwidthUpgradeErrorStage - error_stage) { + BandwidthUpgradeResult result, BandwidthUpgradeErrorStage error_stage, + OperationResultCode operation_result_code) { if (in_progress_upgrades_.size() == 1) { auto it = in_progress_upgrades_.begin(); std::string endpoint_id = it->first; @@ -1441,28 +1500,20 @@ void BwuManager::AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( // them if they want to repeatedly attempt to connect or if they want to // give up and have us try a different medium. This isn't a decision we can // make for them. - client->GetAnalyticsRecorder().OnBandwidthUpgradeError(endpoint_id, result, - error_stage); - NEARBY_LOGS(INFO) - << "BwuManager got error " - << location::nearby::proto::connections::BandwidthUpgradeResult_Name( - result) - << " at stage " - << location::nearby::proto::connections:: - BandwidthUpgradeErrorStage_Name(error_stage) - << " when upgrading endpoint " << endpoint_id; + client->GetAnalyticsRecorder().OnBandwidthUpgradeError( + endpoint_id, result, error_stage, operation_result_code); + NEARBY_LOGS(INFO) << "BwuManager got error " + << BandwidthUpgradeResult_Name(result) << " at stage " + << BandwidthUpgradeErrorStage_Name(error_stage) + << " when upgrading endpoint " << endpoint_id; } // Otherwise, we have no way of knowing which endpoint was trying to connect // to us :( - NEARBY_LOGS(INFO) - << "BwuManager got error " - << location::nearby::proto::connections::BandwidthUpgradeResult_Name( - result) - << " at stage " - << location::nearby::proto::connections::BandwidthUpgradeErrorStage_Name( - error_stage) - << ", but we don't know which endpoint was trying to " - "connect to us, so skipping analytics for his error."; + NEARBY_LOGS(INFO) << "BwuManager got error " + << BandwidthUpgradeResult_Name(result) << " at stage " + << BandwidthUpgradeErrorStage_Name(error_stage) + << ", but we don't know which endpoint was trying to " + "connect to us, so skipping analytics for his error."; } absl::Duration BwuManager::CalculateNextRetryDelay( diff --git a/connections/implementation/bwu_manager.h b/connections/implementation/bwu_manager.h index c13d320837..56f40870f6 100644 --- a/connections/implementation/bwu_manager.h +++ b/connections/implementation/bwu_manager.h @@ -15,7 +15,6 @@ #ifndef CORE_INTERNAL_BWU_MANAGER_H_ #define CORE_INTERNAL_BWU_MANAGER_H_ -#include #include #include #include @@ -26,9 +25,17 @@ #include "absl/time/time.h" #include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" #include "connections/implementation/mediums/mediums.h" +#include "connections/medium_selector.h" +#include "internal/platform/cancelable_alarm.h" +#include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" +#include "internal/platform/runnable.h" #include "internal/platform/scheduled_executor.h" +#include "internal/platform/single_thread_executor.h" namespace nearby { namespace connections { @@ -167,7 +174,8 @@ class BwuManager : public EndpointManager::FrameProcessor { void ProcessBwuPathAvailableEvent(ClientProxy* client, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info); - std::unique_ptr ProcessBwuPathAvailableEventInternal( + ErrorOr> + ProcessBwuPathAvailableEventInternal( ClientProxy* client, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info); void ProcessLastWriteToPriorChannelEvent(ClientProxy* client, @@ -181,9 +189,13 @@ class BwuManager : public EndpointManager::FrameProcessor { void ProcessEndpointDisconnection(ClientProxy* client, const std::string& endpoint_id, CountDownLatch* barrier); - void ProcessUpgradeFailureEvent(ClientProxy* client, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_info); + void ProcessUpgradeFailureEvent( + ClientProxy* client, const std::string& endpoint_id, + const UpgradePathInfo& upgrade_info, + location::nearby::proto::connections::BandwidthUpgradeResult result, + bool record_analytic, + location::nearby::proto::connections::OperationResultCode + operation_result_code); void CancelRetryUpgradeAlarm(const std::string& endpoint_id); void CancelAllRetryUpgradeAlarms(); void TryNextBestUpgradeMediums(ClientProxy* client, @@ -195,7 +207,9 @@ class BwuManager : public EndpointManager::FrameProcessor { void AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( location::nearby::proto::connections::BandwidthUpgradeResult result, location::nearby::proto::connections::BandwidthUpgradeErrorStage - error_stage); + error_stage, + location::nearby::proto::connections::OperationResultCode + operation_result_code); bool is_single_threaded_for_testing_ = false; diff --git a/connections/implementation/client_proxy.cc b/connections/implementation/client_proxy.cc index 174a1a4044..96a1c8847b 100644 --- a/connections/implementation/client_proxy.cc +++ b/connections/implementation/client_proxy.cc @@ -35,7 +35,9 @@ #include "connections/advertising_options.h" #include "connections/connection_options.h" #include "connections/discovery_options.h" +#include "connections/implementation/analytics/advertising_metadata_params.h" #include "connections/implementation/analytics/analytics_recorder.h" +#include "connections/implementation/analytics/discovery_metadata_params.h" #include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "connections/listeners.h" #include "connections/medium_selector.h" @@ -66,7 +68,9 @@ namespace nearby { namespace connections { + namespace { +using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::connections::OsInfo; constexpr char kEndpointIdChars[] = { @@ -79,13 +83,8 @@ bool IsFeatureUseStableEndpointIdEnabled() { connections::config_package_nearby::nearby_connections_feature:: kUseStableEndpointId); } - } // namespace -// The definition is necessary before C++17. -constexpr absl::Duration - ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout; - ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger) : client_id_(Prng().NextInt64()) { NEARBY_LOGS(INFO) << "ClientProxy ctor event_logger=" << event_logger; @@ -216,6 +215,8 @@ void ClientProxy::StartedAdvertising( const std::string& service_id, Strategy strategy, const ConnectionListener& listener, absl::Span mediums, + const std::vector& + operation_result_with_mediums, const AdvertisingOptions& advertising_options) { MutexLock lock(&mutex_); NEARBY_LOGS(INFO) << "ClientProxy [StartedAdvertising]: client=" @@ -244,7 +245,13 @@ void ClientProxy::StartedAdvertising( const std::vector medium_vector( mediums.begin(), mediums.end()); - analytics_recorder_->OnStartAdvertising(strategy, medium_vector, false, 0); + std::unique_ptr advertising_metadata_params; + advertising_metadata_params = + GetAnalyticsRecorder().BuildAdvertisingMetadataParams(); + advertising_metadata_params->operation_result_with_mediums = + std::move(operation_result_with_mediums); + analytics_recorder_->OnStartAdvertising(strategy, medium_vector, + advertising_metadata_params.get()); } void ClientProxy::StoppedAdvertising() { @@ -363,6 +370,8 @@ void ClientProxy::StartedDiscovery( const std::string& service_id, Strategy strategy, DiscoveryListener listener, absl::Span mediums, + const std::vector& + operation_result_with_mediums, const DiscoveryOptions& discovery_options) { MutexLock lock(&mutex_); discovery_info_ = DiscoveryInfo{service_id, std::move(listener)}; @@ -370,7 +379,13 @@ void ClientProxy::StartedDiscovery( const std::vector medium_vector( mediums.begin(), mediums.end()); - analytics_recorder_->OnStartDiscovery(strategy, medium_vector, false, 0); + std::unique_ptr discovery_metadata_params; + discovery_metadata_params = + GetAnalyticsRecorder().BuildDiscoveryMetadataParams(); + discovery_metadata_params->operation_result_with_mediums = + std::move(operation_result_with_mediums); + analytics_recorder_->OnStartDiscovery(strategy, medium_vector, + discovery_metadata_params.get()); } void ClientProxy::StoppedDiscovery() { @@ -558,8 +573,9 @@ void ClientProxy::OnBandwidthChanged(const std::string& endpoint_id, NEARBY_LOGS(INFO) << "ClientProxy [BandwidthChanged]: id=" << endpoint_id; MutexLock lock(&mutex_); - const ConnectionPair* item = LookupConnection(endpoint_id); + ConnectionPair* item = LookupConnection(endpoint_id); if (item != nullptr) { + item->first.connected_medium = new_medium; item->first.connection_listener.bandwidth_changed_cb(endpoint_id, new_medium); NEARBY_LOGS(INFO) << "ClientProxy [reporting onBandwidthChanged]: client=" @@ -600,6 +616,17 @@ bool ClientProxy::ConnectionStatusMatches(const std::string& endpoint_id, return false; } +Medium ClientProxy::GetConnectedMedium(const std::string& endpoint_id) const { + MutexLock lock(&mutex_); + + const ConnectionPair* item = LookupConnection(endpoint_id); + if (item != nullptr) { + return item->first.connected_medium; + } + + return Medium::UNKNOWN_MEDIUM; +} + BooleanMediumSelector ClientProxy::GetUpgradeMediums( const std::string& endpoint_id) const { MutexLock lock(&mutex_); diff --git a/connections/implementation/client_proxy.h b/connections/implementation/client_proxy.h index 881c160577..545a4b4e99 100644 --- a/connections/implementation/client_proxy.h +++ b/connections/implementation/client_proxy.h @@ -53,6 +53,7 @@ #include "absl/types/span.h" #include "internal/platform/os_name.h" #include "internal/platform/scheduled_executor.h" +#include "internal/proto/analytics/connections_log.pb.h" namespace nearby { namespace connections { @@ -101,6 +102,9 @@ class ClientProxy final { const std::string& service_id, Strategy strategy, const ConnectionListener& connection_lifecycle_listener, absl::Span mediums, + const std::vector& + operation_result_with_medium, const AdvertisingOptions& advertising_options = AdvertisingOptions{}); // Marks this client as not advertising. void StoppedAdvertising(); @@ -123,6 +127,9 @@ class ClientProxy final { const std::string& service_id, Strategy strategy, DiscoveryListener discovery_listener, absl::Span mediums, + const std::vector& + operation_result_with_medium, const DiscoveryOptions& discovery_options = DiscoveryOptions{}); // Marks this client as not discovering at all. void StoppedDiscovery(); @@ -179,6 +186,9 @@ class ClientProxy final { // ConnectionListener.disconnected_cb() callback. void OnDisconnected(const std::string& endpoint_id, bool notify); + // Returns the medium we're currently connected to the endpoint over, or + // UNKNOWN if we don't know or don't have a connection. + Medium GetConnectedMedium(const std::string& endpoint_id) const; // Returns all mediums eligible for upgrade. BooleanMediumSelector GetUpgradeMediums(const std::string& endpoint_id) const; // Returns if this endpoint support 5G for WIFI. @@ -363,6 +373,7 @@ class ClientProxy final { kConnected = 1 << 4, }; bool is_incoming{false}; + Medium connected_medium{Medium::UNKNOWN_MEDIUM}; Status status{kPending}; ConnectionListener connection_listener; ConnectionOptions connection_options; diff --git a/connections/implementation/client_proxy_test.cc b/connections/implementation/client_proxy_test.cc index f40ed07015..150b8c476a 100644 --- a/connections/implementation/client_proxy_test.cc +++ b/connections/implementation/client_proxy_test.cc @@ -210,8 +210,9 @@ class ClientProxyTest : public ::testing::TestWithParam { .info = ByteArray{"advertising endpoint name"}, .id = client->GetLocalEndpointId(), }; - client->StartedAdvertising(service_id_, strategy_, listener, - absl::MakeSpan(mediums_), advertising_options); + client->StartedAdvertising( + service_id_, strategy_, listener, absl::MakeSpan(mediums_), + /*operation_result_with_medium=*/{}, advertising_options); return endpoint; } @@ -256,7 +257,8 @@ class ClientProxyTest : public ::testing::TestWithParam { .id = client->GetLocalEndpointId(), }; client->StartedDiscovery(service_id_, strategy_, std::move(listener), - absl::MakeSpan(mediums_)); + absl::MakeSpan(mediums_), + /*operation_result_with_medium=*/{}); return endpoint; } @@ -607,7 +609,7 @@ TEST_F(ClientProxyTest, ResetClearsState) { } TEST_F(ClientProxyTest, StartedAdvertisingChangesStateFromIdle) { - client1()->StartedAdvertising(service_id_, strategy_, {}, {}); + client1()->StartedAdvertising(service_id_, strategy_, {}, {}, {}); EXPECT_TRUE(client1()->IsAdvertising()); EXPECT_FALSE(client1()->IsDiscovering()); @@ -616,7 +618,7 @@ TEST_F(ClientProxyTest, StartedAdvertisingChangesStateFromIdle) { } TEST_F(ClientProxyTest, StartedDiscoveryChangesStateFromIdle) { - client1()->StartedDiscovery(service_id_, strategy_, {}, {}); + client1()->StartedDiscovery(service_id_, strategy_, {}, {}, {}); EXPECT_FALSE(client1()->IsAdvertising()); EXPECT_TRUE(client1()->IsDiscovering()); diff --git a/connections/implementation/endpoint_manager.cc b/connections/implementation/endpoint_manager.cc index 5942072008..26236aaf36 100644 --- a/connections/implementation/endpoint_manager.cc +++ b/connections/implementation/endpoint_manager.cc @@ -30,7 +30,6 @@ #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/offline_frames.h" -#include "connections/implementation/payload_manager.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "connections/implementation/service_id_constants.h" #include "connections/listeners.h" @@ -55,10 +54,10 @@ namespace connections { namespace { using ::location::nearby::analytics::proto::ConnectionsLog; using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::connections::PayloadTransferFrame; using ::location::nearby::connections::V1Frame; +using ::location::nearby::proto::connections::DisconnectionReason; using ::nearby::analytics::PacketMetaData; -using DisconnectionReason = - ::location::nearby::proto::connections::DisconnectionReason; // 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 diff --git a/connections/implementation/fake_bwu_handler.h b/connections/implementation/fake_bwu_handler.h index 6f9aaa910f..d87e99f2d9 100644 --- a/connections/implementation/fake_bwu_handler.h +++ b/connections/implementation/fake_bwu_handler.h @@ -15,6 +15,7 @@ #ifndef NEARBY_CONNECTIONS_IMPLEMENTATION_FAKE_BWU_HANDLER_H_ #define NEARBY_CONNECTIONS_IMPLEMENTATION_FAKE_BWU_HANDLER_H_ +#include #include #include #include @@ -22,9 +23,15 @@ #include #include "connections/implementation/base_bwu_handler.h" +#include "connections/implementation/bwu_handler.h" #include "connections/implementation/bwu_manager.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" #include "connections/implementation/fake_endpoint_channel.h" +#include "connections/implementation/offline_frames.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/exception.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -104,14 +111,15 @@ class FakeBwuHandler : public BaseBwuHandler { }; // BwuHandler: - std::unique_ptr CreateUpgradedEndpointChannel( + ErrorOr> + CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) final { create_calls_.push_back({.client = client, .service_id = service_id, .endpoint_id = endpoint_id}); - return std::make_unique(medium_, service_id); + return {std::make_unique(medium_, service_id)}; } Medium GetUpgradeMedium() const final { return medium_; } diff --git a/connections/implementation/internal_payload_factory.cc b/connections/implementation/internal_payload_factory.cc index 38268fc9eb..382740c0be 100644 --- a/connections/implementation/internal_payload_factory.cc +++ b/connections/implementation/internal_payload_factory.cc @@ -27,6 +27,7 @@ #include "connections/payload_type.h" #include "internal/platform/byte_array.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/file.h" #include "internal/platform/implementation/platform.h" #include "internal/platform/input_stream.h" @@ -40,6 +41,7 @@ namespace connections { namespace { using ::location::nearby::connections::PayloadTransferFrame; +using ::location::nearby::proto::connections::OperationResultCode; class BytesInternalPayload : public InternalPayload { public: @@ -309,23 +311,24 @@ class IncomingFileInternalPayload : public InternalPayload { using ::nearby::api::ImplementationPlatform; using ::nearby::api::OSName; -std::unique_ptr CreateOutgoingInternalPayload( +ErrorOr> CreateOutgoingInternalPayload( Payload payload) { switch (payload.GetType()) { case PayloadType::kBytes: - return std::make_unique(std::move(payload)); + return {std::make_unique(std::move(payload))}; case PayloadType::kFile: { - return std::make_unique(std::move(payload)); + return { + std::make_unique(std::move(payload))}; } case PayloadType::kStream: - return std::make_unique( - std::move(payload)); + return { + std::make_unique(std::move(payload))}; default: DCHECK(false); // This should never happen. - return {}; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } } @@ -350,26 +353,27 @@ std::string make_path(const std::string& custom_save_path, return api::ImplementationPlatform::GetDownloadPath(parent_folder, file_name); } -std::unique_ptr CreateIncomingInternalPayload( +ErrorOr> CreateIncomingInternalPayload( const location::nearby::connections::PayloadTransferFrame& frame, const std::string& custom_save_path) { if (frame.packet_type() != location::nearby::connections::PayloadTransferFrame::DATA) { - return {}; + return {Error( + OperationResultCode::NEARBY_GENERIC_INCOMING_PAYLOAD_NOT_DATA_TYPE)}; } const Payload::Id payload_id = frame.payload_header().id(); switch (frame.payload_header().type()) { case PayloadTransferFrame::PayloadHeader::BYTES: { - return std::make_unique( - Payload(payload_id, ByteArray(frame.payload_chunk().body()))); + return {std::make_unique( + Payload(payload_id, ByteArray(frame.payload_chunk().body())))}; } case PayloadTransferFrame::PayloadHeader::STREAM: { auto [input, output] = CreatePipe(); - return std::make_unique( - Payload(payload_id, std::move(input)), std::move(output)); + return {std::make_unique( + Payload(payload_id, std::move(input)), std::move(output))}; } case PayloadTransferFrame::PayloadHeader::FILE: { @@ -397,7 +401,7 @@ std::unique_ptr CreateIncomingInternalPayload( // file name for the output file. NEARBY_LOGS(ERROR) << "File name not found in incoming file Payload, " "and the Id wasn't found."; - return {}; + return {Error(OperationResultCode::IO_FILE_OPENING_ERROR)}; } } @@ -409,19 +413,19 @@ std::unique_ptr CreateIncomingInternalPayload( // there will be no input file to open. // On Chrome the file path should be empty, so use the payload id. if (ImplementationPlatform::GetCurrentOS() == OSName::kChromeOS) { - return std::make_unique( + return {std::make_unique( Payload(payload_id, InputFile(payload_id, total_size)), - OutputFile(payload_id), total_size); + OutputFile(payload_id), total_size)}; } else { - return std::make_unique( + return {std::make_unique( Payload(payload_id, parent_folder, file_name, InputFile(file_path, total_size)), - OutputFile(file_path), total_size); + OutputFile(file_path), total_size)}; } } default: DCHECK(false); // This should never happen. - return {}; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } } diff --git a/connections/implementation/internal_payload_factory.h b/connections/implementation/internal_payload_factory.h index 6e510ade96..26a41b8015 100644 --- a/connections/implementation/internal_payload_factory.h +++ b/connections/implementation/internal_payload_factory.h @@ -15,22 +15,23 @@ #ifndef CORE_INTERNAL_INTERNAL_PAYLOAD_FACTORY_H_ #define CORE_INTERNAL_INTERNAL_PAYLOAD_FACTORY_H_ -#include - #include +#include #include "connections/implementation/internal_payload.h" #include "connections/payload.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { // Creates an InternalPayload representing an outgoing Payload. -std::unique_ptr CreateOutgoingInternalPayload(Payload payload); +ErrorOr> CreateOutgoingInternalPayload( + Payload payload); // Creates an InternalPayload representing an incoming Payload from a remote // endpoint. -std::unique_ptr CreateIncomingInternalPayload( +ErrorOr> CreateIncomingInternalPayload( const location::nearby::connections::PayloadTransferFrame& frame, const std::string& custom_save_path); diff --git a/connections/implementation/internal_payload_factory_test.cc b/connections/implementation/internal_payload_factory_test.cc index 9f6979aefc..d69e6d7bc4 100644 --- a/connections/implementation/internal_payload_factory_test.cc +++ b/connections/implementation/internal_payload_factory_test.cc @@ -14,6 +14,7 @@ #include "connections/implementation/internal_payload_factory.h" +#include #include #include #include @@ -26,6 +27,7 @@ #include "connections/payload_type.h" #include "internal/platform/byte_array.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/file.h" #include "internal/platform/pipe.h" @@ -38,8 +40,10 @@ constexpr char kText[] = "data chunk"; TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromBytePayload) { ByteArray data(kText); - std::unique_ptr internal_payload = + ErrorOr> result = CreateOutgoingInternalPayload(Payload{data}); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_EQ(payload.AsFile(), nullptr); @@ -49,8 +53,10 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromBytePayload) { TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromStreamPayload) { auto [input, output] = CreatePipe(); - std::unique_ptr internal_payload = + ErrorOr> result = CreateOutgoingInternalPayload(Payload(std::move(input))); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_EQ(payload.AsFile(), nullptr); @@ -61,8 +67,10 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromStreamPayload) { TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromFilePayload) { Payload::Id payload_id = Payload::GenerateId(); InputFile inputFile(payload_id, 512); - std::unique_ptr internal_payload = + ErrorOr> result = CreateOutgoingInternalPayload(Payload{payload_id, std::move(inputFile)}); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_NE(payload.AsFile(), nullptr); @@ -86,8 +94,10 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromByteMessage) { header.set_id(12345); header.set_total_size(512); *frame.mutable_payload_chunk() = std::move(payload_chunk); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_EQ(payload.AsFile(), nullptr); @@ -103,8 +113,10 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromStreamMessage) { header.set_type(PayloadTransferFrame::PayloadHeader::STREAM); header.set_id(12345); header.set_total_size(0); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); { Payload payload = internal_payload->ReleasePayload(); @@ -126,8 +138,10 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromFileMessage) { header.set_type(PayloadTransferFrame::PayloadHeader::FILE); header.set_id(12345); header.set_total_size(512); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_NE(payload.AsFile(), nullptr); @@ -144,9 +158,9 @@ TEST(InternalPayloadFactoryTest, auto& header = *frame.mutable_payload_header(); header.set_type(PayloadTransferFrame::PayloadHeader::FILE); header.set_total_size(512); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); - EXPECT_EQ(internal_payload, nullptr); + EXPECT_TRUE(result.has_error()); } TEST(InternalPayloadFactoryTest, @@ -158,8 +172,10 @@ TEST(InternalPayloadFactoryTest, header.set_type(PayloadTransferFrame::PayloadHeader::FILE); header.set_id(12345); header.set_total_size(512); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); Payload payload = internal_payload->ReleasePayload(); EXPECT_EQ(payload.GetFileName(), "12345"); @@ -174,8 +190,10 @@ TEST(InternalPayloadFactoryTest, header.set_id(12345); header.set_total_size(512); header.set_file_name("test.file.name"); - std::unique_ptr internal_payload = + ErrorOr> result = CreateIncomingInternalPayload(frame, path); + ASSERT_FALSE(result.has_error()); + std::unique_ptr internal_payload = std::move(result.value()); EXPECT_NE(internal_payload, nullptr); auto test = internal_payload->GetFileName(); Payload payload = internal_payload->ReleasePayload(); @@ -196,8 +214,11 @@ TEST(InternalPayloadFactoryTest, Payload::Id payload_id = Payload::GenerateId(); CreateFileWithContents(payload_id, contents); InputFile inputFile(payload_id, contents.size()); - std::unique_ptr internal_payload = + ErrorOr> interal_payload_result = CreateOutgoingInternalPayload(Payload{payload_id, std::move(inputFile)}); + ASSERT_FALSE(interal_payload_result.has_error()); + std::unique_ptr internal_payload = + std::move(interal_payload_result.value()); EXPECT_NE(internal_payload, nullptr); ExceptionOr result = internal_payload->SkipToOffset(kOffset); @@ -215,8 +236,11 @@ TEST(InternalPayloadFactoryTest, ByteArray contents("0123456789"); constexpr size_t kOffset = 6; auto [input, output] = CreatePipe(); - std::unique_ptr internal_payload = + ErrorOr> interal_payload_result = CreateOutgoingInternalPayload(Payload(std::move(input))); + ASSERT_FALSE(interal_payload_result.has_error()); + std::unique_ptr internal_payload = + std::move(interal_payload_result.value()); EXPECT_NE(internal_payload, nullptr); output->Write(contents); diff --git a/connections/implementation/mediums/ble.cc b/connections/implementation/mediums/ble.cc index 887d5ef63e..a864bfb06f 100644 --- a/connections/implementation/mediums/ble.cc +++ b/connections/implementation/mediums/ble.cc @@ -15,14 +15,19 @@ #include "connections/implementation/mediums/ble.h" #include -#include +#include #include #include #include "absl/strings/escaping.h" #include "connections/implementation/mediums/ble_v2/ble_advertisement.h" +#include "connections/implementation/mediums/bluetooth_radio.h" #include "connections/implementation/mediums/utils.h" +#include "internal/platform/ble.h" +#include "internal/platform/bluetooth_adapter.h" #include "internal/platform/byte_array.h" +#include "internal/platform/cancellation_flag.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" #include "internal/platform/mutex_lock.h" #include "internal/platform/prng.h" @@ -30,6 +35,10 @@ namespace nearby { namespace connections { +namespace { +using location::nearby::proto::connections::OperationResultCode; +} // namespace + ByteArray Ble::GenerateHash(const std::string& source, size_t size) { return Utils::Sha256Hash(source, size); } @@ -144,8 +153,8 @@ bool Ble::StopAdvertising(const std::string& service_id) { bool Ble::StartLegacyAdvertising( const std::string& input_service_id, const std::string& local_endpoint_id, const std::string& fast_advertisement_service_uuid) { - NEARBY_LOGS(INFO) << "StartLegacyAdvertising: " << input_service_id.c_str() - << ", local_endpoint_id: " << local_endpoint_id.c_str(); + NEARBY_LOGS(INFO) << "StartLegacyAdvertising: " << input_service_id + << ", local_endpoint_id: " << local_endpoint_id; MutexLock lock(&mutex_); std::string service_id = input_service_id + "-Legacy"; @@ -195,7 +204,7 @@ bool Ble::StartLegacyAdvertising( } bool Ble::StopLegacyAdvertising(const std::string& input_service_id) { - NEARBY_LOGS(INFO) << "StopLegacyAdvertising:" << input_service_id.c_str(); + NEARBY_LOGS(INFO) << "StopLegacyAdvertising:" << input_service_id; MutexLock lock(&mutex_); std::string service_id = input_service_id + "-Legacy"; @@ -384,8 +393,9 @@ bool Ble::IsAcceptingConnectionsLocked(const std::string& service_id) { return accepting_connections_info_.Existed(service_id); } -BleSocket Ble::Connect(BlePeripheral& peripheral, const std::string& service_id, - CancellationFlag* cancellation_flag) { +ErrorOr Ble::Connect(BlePeripheral& peripheral, + const std::string& service_id, + CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); NEARBY_LOGS(INFO) << "BLE::Connect: service=" << &peripheral; // Socket to return. To allow for NRVO to work, it has to be a single object. @@ -393,24 +403,26 @@ BleSocket Ble::Connect(BlePeripheral& peripheral, const std::string& service_id, if (service_id.empty()) { NEARBY_LOGS(INFO) << "Refusing to create BLE socket with empty service_id."; - return socket; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!radio_.IsEnabled()) { NEARBY_LOGS(INFO) << "Can't create client BLE socket to " << &peripheral << " because Bluetooth isn't enabled."; - return socket; + return {Error(OperationResultCode::MISCELLEANEOUS_BLE_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't create client BLE socket [service_id=" << service_id << "]; BLE isn't available."; - return socket; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } if (cancellation_flag->Cancelled()) { NEARBY_LOGS(INFO) << "Can't create client BLE socket due to cancel."; - return socket; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_BLE_OUTGOING_CONNECTION)}; } socket = medium_.Connect(peripheral, service_id, cancellation_flag); @@ -428,7 +440,7 @@ ByteArray Ble::UnwrapAdvertisementBytes( mediums::BleAdvertisement::CreateBleAdvertisement( medium_advertisement_data); if (!medium_ble_advertisement_status_or.ok()) { - NEARBY_LOGS(INFO) << medium_ble_advertisement_status_or.status().ToString(); + NEARBY_LOGS(INFO) << medium_ble_advertisement_status_or.status(); return ByteArray(); } diff --git a/connections/implementation/mediums/ble.h b/connections/implementation/mediums/ble.h index 2502f92bbf..f21aa1b760 100644 --- a/connections/implementation/mediums/ble.h +++ b/connections/implementation/mediums/ble.h @@ -15,16 +15,17 @@ #ifndef CORE_INTERNAL_MEDIUMS_BLE_H_ #define CORE_INTERNAL_MEDIUMS_BLE_H_ -#include #include -#include "absl/container/flat_hash_map.h" +#include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_set.h" #include "connections/implementation/mediums/bluetooth_radio.h" #include "connections/listeners.h" +#include "internal/platform/ble.h" +#include "internal/platform/bluetooth_adapter.h" #include "internal/platform/byte_array.h" #include "internal/platform/cancellation_flag.h" -#include "internal/platform/ble.h" +#include "internal/platform/expected.h" #include "internal/platform/multi_thread_executor.h" #include "internal/platform/mutex.h" @@ -111,8 +112,9 @@ class Ble { // service_id. Blocks until connection is established, or server-side is // terminated. Returns socket instance. On success, BleSocket.IsValid() return // true. - BleSocket Connect(BlePeripheral& peripheral, const std::string& service_id, - CancellationFlag* cancellation_flag) + ErrorOr Connect(BlePeripheral& peripheral, + const std::string& service_id, + CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); private: diff --git a/connections/implementation/mediums/ble_test.cc b/connections/implementation/mediums/ble_test.cc index c88cb51c2d..0382381b6d 100644 --- a/connections/implementation/mediums/ble_test.cc +++ b/connections/implementation/mediums/ble_test.cc @@ -26,6 +26,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" @@ -100,9 +101,11 @@ TEST_P(BleTest, CanStartAcceptingConnectionsAndConnect) { BlePeripheral discovered_peripheral = atomic_discovered_peripheral.load(); ASSERT_TRUE(discovered_peripheral.IsValid()); CancellationFlag flag; - BleSocket socket = ble_b.Connect(discovered_peripheral, service_id, &flag); + ErrorOr socket_result = + ble_b.Connect(discovered_peripheral, service_id, &flag); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(socket.IsValid()); + EXPECT_TRUE(socket_result.has_value()); + EXPECT_TRUE(socket_result.value().IsValid()); ble_b.StopScanning(service_id); ble_a.StopAdvertising(service_id); env_.Stop(); @@ -151,14 +154,16 @@ TEST_P(BleTest, CanCancelConnect) { BlePeripheral discovered_peripheral = atomic_discovered_peripheral.load(); ASSERT_TRUE(discovered_peripheral.IsValid()); CancellationFlag flag(true); - BleSocket socket = ble_b.Connect(discovered_peripheral, service_id, &flag); + ErrorOr socket_result = + ble_b.Connect(discovered_peripheral, service_id, &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(socket.IsValid()); + EXPECT_TRUE(socket_result.has_value()); + EXPECT_TRUE(socket_result.value().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); - EXPECT_FALSE(socket.IsValid()); + EXPECT_TRUE(socket_result.has_error()); } ble_b.StopScanning(service_id); ble_a.StopAdvertising(service_id); diff --git a/connections/implementation/mediums/ble_v2.cc b/connections/implementation/mediums/ble_v2.cc index 20953f8c69..20d34b461c 100644 --- a/connections/implementation/mediums/ble_v2.cc +++ b/connections/implementation/mediums/ble_v2.cc @@ -44,6 +44,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancelable_alarm.h" #include "internal/platform/cancellation_flag.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/ble_v2.h" #include "internal/platform/logging.h" @@ -56,7 +57,7 @@ namespace nearby { namespace connections { namespace { - +using ::location::nearby::proto::connections::OperationResultCode; using ::nearby::api::ble_v2::BleAdvertisementData; using ::nearby::api::ble_v2::GattCharacteristic; using ::nearby::api::ble_v2::TxPowerLevel; @@ -109,16 +110,16 @@ bool BleV2::IsAvailable() const { return IsAvailableLocked(); } -bool BleV2::StartAdvertising(const std::string& service_id, - const ByteArray& advertisement_bytes, - PowerLevel power_level, - bool is_fast_advertisement) { +ErrorOr BleV2::StartAdvertising(const std::string& service_id, + const ByteArray& advertisement_bytes, + PowerLevel power_level, + bool is_fast_advertisement) { MutexLock lock(&mutex_); if (advertisement_bytes.Empty()) { LOG(INFO) << "Refusing to turn on BLE advertising. Empty advertisement data."; - return false; + return {Error(OperationResultCode::NEARBY_BLE_ADVERTISE_TO_BYTES_FAILURE)}; } if (advertisement_bytes.size() > kMaxAdvertisementLength) { @@ -126,23 +127,23 @@ bool BleV2::StartAdvertising(const std::string& service_id, "advertisement was too long. Expected at most " << kMaxAdvertisementLength << " bytes but received " << advertisement_bytes.size() << " bytes."; - return false; + return {Error(OperationResultCode::NEARBY_BLE_ADVERTISE_TO_BYTES_FAILURE)}; } if (IsAdvertisingLocked(service_id)) { LOG(INFO) << "Failed to BLE advertise because we're already advertising."; - return false; + return {Error(OperationResultCode::CLIENT_BLE_DUPLICATE_DISCOVERING)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't start BLE advertising because Bluetooth was never turned on"; - return false; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't turn on BLE advertising. BLE is not available."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } // Wrap the connections advertisement to the medium advertisement. @@ -161,7 +162,7 @@ bool BleV2::StartAdvertising(const std::string& service_id, if (!medium_advertisement.IsValid()) { LOG(INFO) << "Failed to BLE advertise because we could not wrap a " "connection advertisement to medium advertisement."; - return false; + return {Error(OperationResultCode::NEARBY_BLE_ADVERTISE_TO_BYTES_FAILURE)}; } advertising_infos_.insert( @@ -180,9 +181,10 @@ bool BleV2::StartAdvertising(const std::string& service_id, if (!StartAdvertisingLocked(service_id)) { advertising_infos_.erase(service_id); - return false; + return { + Error(OperationResultCode::CONNECTIVITY_BLE_START_ADVERTISING_FAILURE)}; } - return true; + return {true}; } bool BleV2::StopAdvertising(const std::string& service_id) { @@ -257,7 +259,7 @@ bool BleV2::IsAdvertisingForLegacyDevice(const std::string& service_id) const { return IsAdvertisingForLegacyDeviceLocked(service_id); } -bool BleV2::StartLegacyAdvertising( +ErrorOr BleV2::StartLegacyAdvertising( const std::string& input_service_id, const std::string& local_endpoint_id, const std::string& fast_advertisement_service_uuid) { LOG(INFO) << "StartLegacyAdvertising: " << input_service_id @@ -267,12 +269,12 @@ bool BleV2::StartLegacyAdvertising( if (!radio_.IsEnabled()) { LOG(INFO) << "Can't start BLE v2 legacy advertising because " "Bluetooth was never turned on"; - return false; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't turn on BLE v2 legacy advertising. BLE is not available."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } if (medium_.IsExtendedAdvertisementsAvailable()) { LOG(INFO) << "Skip dummy advertising for non legacy device"; @@ -282,7 +284,7 @@ bool BleV2::StartLegacyAdvertising( if (service_ids_to_advertising_sessions_.find(service_id) != service_ids_to_advertising_sessions_.end()) { LOG(INFO) << "Already started legacy device advertising for " << service_id; - return false; + return {Error(OperationResultCode::CLIENT_BLE_DUPLICATE_ADVERTISING)}; } std::unique_ptr @@ -310,12 +312,13 @@ bool BleV2::StartLegacyAdvertising( LOG(ERROR) << "Failed to turn on BLE v2 advertising for legacy " "device for service ID " << service_id; - return false; + return { + Error(OperationResultCode::CONNECTIVITY_BLE_START_ADVERTISING_FAILURE)}; } service_ids_to_advertising_sessions_.insert( {std::string(service_id), std::move(legacy_device_advertizing_session)}); - return true; + return {true}; } bool BleV2::StopLegacyAdvertising(const std::string& input_service_id) { @@ -343,29 +346,31 @@ bool BleV2::StopLegacyAdvertising(const std::string& input_service_id) { return status.ok(); } -bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level, - DiscoveredPeripheralCallback callback) { +ErrorOr BleV2::StartScanning(const std::string& service_id, + PowerLevel power_level, + DiscoveredPeripheralCallback callback) { MutexLock lock(&mutex_); if (service_id.empty()) { LOG(INFO) << "Can not start BLE scanning with empty service id."; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (IsScanningLocked(service_id)) { LOG(INFO) << "Cannot start scan of BLE peripherals because " "scanning is already in-progress."; - return false; + return {Error(OperationResultCode::CLIENT_BLE_DUPLICATE_DISCOVERING)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't start BLE scanning because Bluetooth is disabled"; - return false; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't scan BLE peripherals because BLE isn't available."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } // Start to track the advertisement found for specific `service_id`. @@ -383,7 +388,7 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level, scanned_service_ids_.insert(service_id); LOG(INFO) << "Turned on BLE scanning with service id=" << service_id << " without start client scanning"; - return true; + return {true}; } scanned_service_ids_.insert(service_id); @@ -426,7 +431,7 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level, discovered_peripheral_tracker_.StopTracking(service_id); // Erase the service id that is just added. scanned_service_ids_.erase(service_id); - return false; + return {Error(OperationResultCode::CONNECTIVITY_BLE_SCAN_FAILURE)}; } absl::Duration peripheral_lost_timeout = @@ -443,7 +448,7 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level, peripheral_lost_timeout, &alarm_executor_, /*is_recurring=*/true); LOG(INFO) << "Turned on BLE scanning with service id=" << service_id; - return true; + return {true}; } bool BleV2::StopScanning(const std::string& service_id) { @@ -482,40 +487,42 @@ bool BleV2::IsScanning(const std::string& service_id) const { return IsScanningLocked(service_id); } -bool BleV2::StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) { +ErrorOr BleV2::StartAcceptingConnections( + const std::string& service_id, AcceptedConnectionCallback callback) { MutexLock lock(&mutex_); if (service_id.empty()) { LOG(INFO) << "Refusing to start accepting BLE connections with empty service id."; - return false; + return {Error(OperationResultCode::CLIENT_BLE_DUPLICATE_DISCOVERING)}; } if (IsAcceptingConnectionsLocked(service_id)) { LOG(INFO) << "Refusing to start accepting BLE connections for " << service_id << " because another BLE peripheral socket is already in-progress."; - return false; + return {Error(OperationResultCode:: + CLIENT_DUPLICATE_ACCEPTING_BLE_CONNECTION_REQUEST)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't start accepting BLE connections for " << service_id << " because Bluetooth isn't enabled."; - return false; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't start accepting BLE connections for " << service_id << " because BLE isn't available."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } BleV2ServerSocket server_socket = medium_.OpenServerSocket(service_id); if (!server_socket.IsValid()) { LOG(INFO) << "Failed to start accepting Ble connections for service_id=" << service_id; - return false; + return {Error( + OperationResultCode::CONNECTIVITY_BLE_SERVER_SOCKET_CREATION_FAILURE)}; } // Mark the fact that there's an in-progress Ble server accepting @@ -552,7 +559,7 @@ bool BleV2::StartAcceptingConnections(const std::string& service_id, } }); - return true; + return {true}; } bool BleV2::StopAcceptingConnections(const std::string& service_id) { @@ -595,9 +602,9 @@ bool BleV2::IsAcceptingConnections(const std::string& service_id) { return IsAcceptingConnectionsLocked(service_id); } -BleV2Socket BleV2::Connect(const std::string& service_id, - const BleV2Peripheral& peripheral, - CancellationFlag* cancellation_flag) { +ErrorOr BleV2::Connect(const std::string& service_id, + const BleV2Peripheral& peripheral, + CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); // Socket to return. To allow for NRVO to work, it has to be a single object. BleV2Socket socket; @@ -605,18 +612,20 @@ BleV2Socket BleV2::Connect(const std::string& service_id, if (service_id.empty()) { LOG(INFO) << "Refusing to create client Ble socket because " "service_id is empty."; - return socket; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't create client Ble socket [service_id=" << service_id << "]; Ble isn't available."; - return socket; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; } if (cancellation_flag->Cancelled()) { LOG(INFO) << "Can't create client Ble socket due to cancel."; - return socket; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_BLE_OUTGOING_CONNECTION)}; } socket = medium_.Connect(service_id, @@ -624,6 +633,8 @@ BleV2Socket BleV2::Connect(const std::string& service_id, peripheral, cancellation_flag); if (!socket.IsValid()) { LOG(INFO) << "Failed to Connect via Ble [service_id=" << service_id << "]"; + return {Error( + OperationResultCode::CONNECTIVITY_BLE_CLIENT_SOCKET_CREATION_FAILURE)}; } return socket; diff --git a/connections/implementation/mediums/ble_v2.h b/connections/implementation/mediums/ble_v2.h index 2879cd5538..1216c107c3 100644 --- a/connections/implementation/mediums/ble_v2.h +++ b/connections/implementation/mediums/ble_v2.h @@ -38,6 +38,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancelable_alarm.h" #include "internal/platform/cancellation_flag.h" +#include "internal/platform/expected.h" #include "internal/platform/implementation/ble_v2.h" #include "internal/platform/multi_thread_executor.h" #include "internal/platform/mutex.h" @@ -74,9 +75,10 @@ class BleV2 final { // power_level - The power level to use for the advertisement. // is_fast_advertisement - True to use fast advertisements, which are smaller // but much more efficient to discover. - bool StartAdvertising(const std::string& service_id, - const ByteArray& advertisement_bytes, - PowerLevel power_level, bool is_fast_advertisement) + ErrorOr StartAdvertising(const std::string& service_id, + const ByteArray& advertisement_bytes, + PowerLevel power_level, + bool is_fast_advertisement) ABSL_LOCKS_EXCLUDED(mutex_); // Disables BLE advertising. @@ -91,7 +93,7 @@ class BleV2 final { // Use dummy bytes to do ble advertising, only for legacy devices. // Returns true, if data is successfully set, and false otherwise. - bool StartLegacyAdvertising( + ErrorOr StartLegacyAdvertising( const std::string& service_id, const std::string& local_endpoint_id, const std::string& fast_advertisement_service_uuid) ABSL_LOCKS_EXCLUDED(mutex_); @@ -109,8 +111,9 @@ class BleV2 final { // power_level - The power level to use for the discovery. // discovered_peripheral_callback - The callback to invoke for discovery // events. - bool StartScanning(const std::string& service_id, PowerLevel power_level, - DiscoveredPeripheralCallback callback) + ErrorOr StartScanning(const std::string& service_id, + PowerLevel power_level, + DiscoveredPeripheralCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Disables BLE scanning for a service ID. @@ -123,8 +126,8 @@ class BleV2 final { // Starts a worker thread, creates a Ble socket, associates it with a // service id. - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) + ErrorOr StartAcceptingConnections(const std::string& service_id, + AcceptedConnectionCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Closes socket corresponding to a service id. @@ -136,9 +139,9 @@ class BleV2 final { // Establishes connection to Ble peripheral. // Returns socket instance. On success, BleSocket.IsValid() return true. - BleV2Socket Connect(const std::string& service_id, - const BleV2Peripheral& peripheral, - CancellationFlag* cancellation_flag) + ErrorOr Connect(const std::string& service_id, + const BleV2Peripheral& peripheral, + CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); // Returns true if this object owns a valid platform implementation. diff --git a/connections/implementation/mediums/ble_v2_test.cc b/connections/implementation/mediums/ble_v2_test.cc index 39f22bf3ee..8c9d55c21b 100644 --- a/connections/implementation/mediums/ble_v2_test.cc +++ b/connections/implementation/mediums/ble_v2_test.cc @@ -30,6 +30,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" @@ -120,15 +121,16 @@ TEST_P(BleV2Test, CanConnect) { ASSERT_TRUE(discovered_peripheral.IsValid()); CancellationFlag flag; - BleV2Socket socket_for_client = + ErrorOr socket_for_client_result = ble_client.Connect(service_id, discovered_peripheral, &flag); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(ble_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(ble_server.StopAdvertising(service_id)); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); EXPECT_TRUE(socket_for_server.GetRemotePeripheral().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemotePeripheral().IsValid()); + EXPECT_TRUE(socket_for_client_result.value().GetRemotePeripheral().IsValid()); env_.Stop(); } @@ -179,7 +181,7 @@ TEST_P(BleV2Test, CanCancelConnect) { ASSERT_TRUE(discovered_peripheral.IsValid()); CancellationFlag flag(true); - BleV2Socket socket_for_client = + ErrorOr socket_for_client_result = ble_client.Connect(service_id, discovered_peripheral, &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { @@ -187,15 +189,17 @@ TEST_P(BleV2Test, CanCancelConnect) { EXPECT_TRUE(ble_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(ble_server.StopAdvertising(service_id)); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); EXPECT_TRUE(socket_for_server.GetRemotePeripheral().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemotePeripheral().IsValid()); + EXPECT_TRUE( + socket_for_client_result.value().GetRemotePeripheral().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(ble_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(ble_server.StopAdvertising(service_id)); EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); } env_.Stop(); } diff --git a/connections/implementation/mediums/bluetooth_classic.cc b/connections/implementation/mediums/bluetooth_classic.cc index d477c8f2e2..3f9d90167d 100644 --- a/connections/implementation/mediums/bluetooth_classic.cc +++ b/connections/implementation/mediums/bluetooth_classic.cc @@ -26,6 +26,7 @@ #include "internal/platform/bluetooth_adapter.h" #include "internal/platform/bluetooth_classic.h" #include "internal/platform/cancellation_flag.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" #include "internal/platform/mutex_lock.h" #include "internal/platform/socket.h" @@ -36,6 +37,8 @@ namespace nearby { namespace connections { namespace { +using location::nearby::proto::connections::OperationResultCode; + std::string ScanModeToString(BluetoothAdapter::ScanMode mode) { switch (mode) { case BluetoothAdapter::ScanMode::kUnknown: @@ -103,36 +106,42 @@ bool BluetoothClassic::IsAvailableLocked() const { return medium_->IsValid() && adapter_.IsValid() && adapter_.IsEnabled(); } -bool BluetoothClassic::TurnOnDiscoverability(const std::string& device_name) { +ErrorOr BluetoothClassic::TurnOnDiscoverability( + const std::string& device_name) { LOG(INFO) << "Turning on BT discoverability with device_name=" << device_name; MutexLock lock(&mutex_); if (device_name.empty()) { LOG(INFO) << "Refusing to turn on BT discoverability. Empty device name."; - return false; + return {Error( + OperationResultCode::NEARBY_BLUETOOTH_ADVERTISE_TO_BYTES_FAILURE)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't turn on BT discoverability. BT is off."; - return false; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't turn on BT discoverability. BT is not available."; - return false; + return { + Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLUETOOTH_NOT_AVAILABLE)}; } if (IsDiscoverable()) { LOG(INFO) << "Refusing to turn on BT discoverability; new name='" << device_name << "'; current name='" << adapter_.GetName() << "'"; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error( + OperationResultCode::CONNECTIVITY_BLUETOOTH_CHANGE_SCAN_MODE_FAILURE)}; } if (!ModifyDeviceName(device_name)) { LOG(INFO) << "Failed to turn on BT discoverability; failed to set name to " << device_name; - return false; + return {Error(OperationResultCode:: + MISCELLEANEOUS_BLUETOOTH_CHANGE_DEVICE_NAME_FAILURE)}; } if (!ModifyScanMode(ScanMode::kConnectableDiscoverable)) { @@ -143,11 +152,12 @@ bool BluetoothClassic::TurnOnDiscoverability(const std::string& device_name) { // Don't forget to perform this rollback of the partial state changes we've // made til now. RestoreDeviceName(); - return false; + return {Error( + OperationResultCode::CONNECTIVITY_BLUETOOTH_CHANGE_SCAN_MODE_FAILURE)}; } LOG(INFO) << "Turned on BT discoverability with device_name=" << device_name; - return true; + return {true}; } bool BluetoothClassic::TurnOffDiscoverability() { @@ -217,30 +227,32 @@ bool BluetoothClassic::RestoreDeviceName() { return true; } -bool BluetoothClassic::StartDiscovery(const std::string& serviceId, - DiscoveredDeviceCallback callback) { +ErrorOr BluetoothClassic::StartDiscovery( + const std::string& serviceId, DiscoveredDeviceCallback callback) { MutexLock lock(&mutex_); if (serviceId.empty()) { LOG(INFO) << "Refusing to start discovery; service ID is empty."; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't discover BT devices because BT isn't enabled."; - return false; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't discover BT devices because BT isn't available."; - return false; + return { + Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLUETOOTH_NOT_AVAILABLE)}; } if (IsDiscoveringLocked(serviceId)) { LOG(INFO) << "Refusing to start discovery of BT devices because another " "discovery is already in-progress for service_id=" << serviceId; - return false; + return {Error(OperationResultCode::CLIENT_BLUETOOTH_DUPLICATE_DISCOVERING)}; } if (!HasDiscoveryCallbacks()) { @@ -275,17 +287,18 @@ bool BluetoothClassic::StartDiscovery(const std::string& serviceId, AddDiscoveryCallback(serviceId, std::move(callback)); + // TODO(edwinwu): See if platform code needs to return ErrorOr if (!medium_->StartDiscovery(std::move(medium_callback))) { LOG(INFO) << "Failed to start discovery of BT devices."; RemoveDiscoveryCallback(serviceId); - return false; + return {Error(OperationResultCode::CONNECTIVITY_BLUETOOTH_SCAN_FAILURE)}; } } // Mark the fact that we're currently performing a Bluetooth scan. scan_info_.valid = true; - return true; + return {true}; } bool BluetoothClassic::StopDiscovery(const std::string& serviceId) { @@ -324,33 +337,36 @@ void BluetoothClassic::StopAllDiscovery() { scan_info_.valid = false; } -bool BluetoothClassic::StartAcceptingConnections( +ErrorOr BluetoothClassic::StartAcceptingConnections( const std::string& service_id, AcceptedConnectionCallback callback) { MutexLock lock(&mutex_); if (service_id.empty()) { LOG(INFO) << "Refusing to start accepting BT connections; service ID is empty."; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!radio_.IsEnabled()) { LOG(INFO) << "Can't create BT server socket [service=" << service_id << "]; BT is disabled."; - return false; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; } if (!IsAvailableLocked()) { LOG(INFO) << "Can't start accepting BT connections [service=" << service_id << "]; BT not available."; - return false; + return { + Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLUETOOTH_NOT_AVAILABLE)}; } if (IsAcceptingConnectionsLocked(service_id)) { LOG(INFO) << "Refusing to start accepting BT connections [service=" << service_id << "]; BT server is already in-progress with the same name."; - return false; + return {Error( + OperationResultCode::CLIENT_DUPLICATE_ACCEPTING_BT_CONNECTION_REQUEST)}; } BluetoothServerSocket socket = @@ -358,7 +374,8 @@ bool BluetoothClassic::StartAcceptingConnections( if (!socket.IsValid()) { LOG(INFO) << "Failed to start accepting Bluetooth connections for " << service_id; - return false; + return {Error( + OperationResultCode::CONNECTIVITY_BT_SERVER_SOCKET_CREATION_FAILURE)}; } // Mark the fact that there's an in-progress Bluetooth server accepting @@ -428,7 +445,7 @@ bool BluetoothClassic::StartAcceptingConnections( } }); - return true; + return {true}; } bool BluetoothClassic::IsAcceptingConnections(const std::string& service_id) { @@ -486,9 +503,9 @@ bool BluetoothClassic::StopAcceptingConnections(const std::string& service_id) { return true; } -BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, - const std::string& service_id, - CancellationFlag* cancellation_flag) { +ErrorOr BluetoothClassic::Connect( + BluetoothDevice& bluetooth_device, const std::string& service_id, + CancellationFlag* cancellation_flag) { { MutexLock lock(&mutex_); if (is_multiplex_enabled_) { @@ -504,7 +521,8 @@ BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, if (bluetooth_socket == nullptr) { LOG(INFO) << "Failed to cast to BluetoothSocket for " << service_id << " with " << bluetooth_device.GetName(); - return BluetoothSocket{}; + return {Error(OperationResultCode:: + NEARBY_BT_VIRTUAL_SOCKET_CREATION_FAILURE)}; } return *bluetooth_socket; } @@ -518,26 +536,30 @@ BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, LOG(WARNING) << "Attempt #" << service_id_to_connect_attempts_count_map_[service_id] << ": Cannot start creating client BT socket due to cancel."; - return BluetoothSocket{}; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_BT_OUTGOING_CONNECTION)}; } - auto wrapper_result = + ErrorOr wrapper_result = AttemptToConnect(bluetooth_device, service_id, cancellation_flag); LOG(INFO) << "Attempt #" << service_id_to_connect_attempts_count_map_[service_id] - << " to connect: " << wrapper_result.IsValid(); - if (wrapper_result.IsValid()) { - return wrapper_result; + << " to connect: " + << (wrapper_result.has_value() ? wrapper_result.value().IsValid() + : false); + if (wrapper_result.has_value() && wrapper_result.value().IsValid()) { + return std::move(wrapper_result.value()); } service_id_to_connect_attempts_count_map_[service_id]++; } LOG(WARNING) << "Giving up after " << kConnectAttemptsLimit << " attempts"; - return BluetoothSocket{}; + return {Error( + OperationResultCode::DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS)}; } -BluetoothSocket BluetoothClassic::AttemptToConnect( +ErrorOr BluetoothClassic::AttemptToConnect( BluetoothDevice& bluetooth_device, const std::string& service_id, CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); @@ -549,24 +571,27 @@ BluetoothSocket BluetoothClassic::AttemptToConnect( if (service_id.empty()) { LOG(WARNING) << "Refusing to create client BT socket because service_id is empty."; - return socket; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!radio_.IsEnabled()) { LOG(WARNING) << "Can't create client BT socket [service=" << service_id << "]: BT isn't enabled."; - return socket; + return {Error(OperationResultCode::MISCELLEANEOUS_BT_SYSTEM_SERVICE_NULL)}; } if (!IsAvailableLocked()) { LOG(WARNING) << "Can't create client BT socket [service=" << service_id << "]; BT isn't available."; - return socket; + return { + Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLUETOOTH_NOT_AVAILABLE)}; } if (!bluetooth_device.IsValid()) { LOG(WARNING) << "Bluetooth device is not valid."; - return socket; + return {Error( + OperationResultCode::CONNECTIVITY_BLUETOOTH_DEVICE_OBTAIN_FAILURE)}; } socket = medium_->ConnectToService( @@ -577,7 +602,8 @@ BluetoothSocket BluetoothClassic::AttemptToConnect( // CancellationFlagListener because the attempt logic is not asynchronous. if (!socket.IsValid() || cancellation_flag->Cancelled()) { LOG(INFO) << "Failed to Connect via BT [service=" << service_id << "]"; - return BluetoothSocket{}; + return {Error( + OperationResultCode::CONNECTIVITY_BT_CLIENT_SOCKET_CREATION_FAILURE)}; } if (is_multiplex_enabled_) { @@ -593,7 +619,8 @@ BluetoothSocket BluetoothClassic::AttemptToConnect( if (bluetooth_socket == nullptr) { LOG(INFO) << "Failed to cast to BluetoothSocket for " << service_id << " with " << bluetooth_device.GetName(); - return BluetoothSocket{}; + return {Error( + OperationResultCode::NEARBY_BT_VIRTUAL_SOCKET_CREATION_FAILURE)}; } LOG(INFO) << "Multiplex socket created for " << bluetooth_device.GetName(); multiplex_sockets_.emplace(bluetooth_device.GetMacAddress(), diff --git a/connections/implementation/mediums/bluetooth_classic.h b/connections/implementation/mediums/bluetooth_classic.h index 4115af0902..f1d105be99 100644 --- a/connections/implementation/mediums/bluetooth_classic.h +++ b/connections/implementation/mediums/bluetooth_classic.h @@ -29,6 +29,7 @@ #include "internal/platform/bluetooth_adapter.h" #include "internal/platform/bluetooth_classic.h" #include "internal/platform/cancellation_flag.h" +#include "internal/platform/expected.h" #include "internal/platform/multi_thread_executor.h" #include "internal/platform/mutex.h" @@ -54,7 +55,7 @@ class BluetoothClassic { // Returns true, if name and scan mode are successfully set, and false // otherwise. // Called by server. - bool TurnOnDiscoverability(const std::string& device_name) + ErrorOr TurnOnDiscoverability(const std::string& device_name) ABSL_LOCKS_EXCLUDED(mutex_); // Disables BT discoverability, and restores scan mode and device name to @@ -67,8 +68,8 @@ class BluetoothClassic { // Enables BT discovery for serviceId. If it is the first call to start // discovery, will enable BT discovery mode. // Returns true, if discovery enabled for serviceId, false otherwise. - bool StartDiscovery(const std::string& serviceId, - DiscoveredDeviceCallback callback) + ErrorOr StartDiscovery(const std::string& serviceId, + DiscoveredDeviceCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Disables BT discovery for serviceId. @@ -83,8 +84,8 @@ class BluetoothClassic { // Any connected sockets returned from Accept() are passed to a callback. // Returns true, if server socket was successfully created, false otherwise. // Called by server. - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) + ErrorOr StartAcceptingConnections(const std::string& service_id, + AcceptedConnectionCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Returns true, if object is currently running a Accept() loop. @@ -114,9 +115,9 @@ class BluetoothClassic { // Blocks until connection is established, or server-side is terminated. // Returns socket instance. On success, BluetoothSocket.IsValid() return true. // Called by client. - BluetoothSocket Connect(BluetoothDevice& bluetooth_device, - const std::string& service_id, - CancellationFlag* cancellation_flag) + ErrorOr Connect(BluetoothDevice& bluetooth_device, + const std::string& service_id, + CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); std::string GetMacAddress() const ABSL_LOCKS_EXCLUDED(mutex_); @@ -185,9 +186,9 @@ class BluetoothClassic { // Blocks until connection is established, or server-side is terminated. // Returns socket instance. On success, BluetoothSocket.IsValid() return true. // Called by client. - BluetoothSocket AttemptToConnect(BluetoothDevice& bluetooth_device, - const std::string& service_id, - CancellationFlag* cancellation_flag); + ErrorOr AttemptToConnect( + BluetoothDevice& bluetooth_device, const std::string& service_id, + CancellationFlag* cancellation_flag); // Accesses to discovery callbacks. bool HasDiscoveryCallbacks() const diff --git a/connections/implementation/mediums/bluetooth_classic_test.cc b/connections/implementation/mediums/bluetooth_classic_test.cc index 0da5e5252a..b4f0c2cbb3 100644 --- a/connections/implementation/mediums/bluetooth_classic_test.cc +++ b/connections/implementation/mediums/bluetooth_classic_test.cc @@ -16,7 +16,6 @@ #include #include -#include #include "gtest/gtest.h" #include "absl/strings/string_view.h" @@ -26,6 +25,7 @@ #include "internal/platform/bluetooth_classic.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/system_clock.h" #include "internal/platform/logging.h" @@ -162,24 +162,24 @@ TEST_P(BluetoothClassicTest, CanNotConnect) { // Cannot connect to an empty service id. CancellationFlag flag; BluetoothDevice discovered_device; - BluetoothSocket socket_for_client = + ErrorOr socket_for_client_result = bt_client.Connect(discovered_device, "", &flag); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); // Cannot connect when radio is disabled. radio_for_client.Disable(); - socket_for_client = + socket_for_client_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); radio_for_client.Enable(); // Cannot connect when adapter is disabled. radio_for_client.GetBluetoothAdapter().SetStatus( BluetoothAdapter::Status::kDisabled); - socket_for_client = + socket_for_client_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); } TEST_P(BluetoothClassicTest, CannotStartAcceptingConnections) { @@ -285,14 +285,15 @@ TEST_P(BluetoothClassicTest, CanConnect) { accept_latch.CountDown(); })); CancellationFlag flag; - BluetoothSocket socket_for_client = + ErrorOr socket_for_client_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client_result.value().GetRemoteDevice().IsValid()); } TEST_P(BluetoothClassicTest, CanCancelBeforeConnect) { @@ -335,21 +336,22 @@ TEST_P(BluetoothClassicTest, CanCancelBeforeConnect) { accept_latch.CountDown(); })); CancellationFlag flag(true); - BluetoothSocket socket_for_client = + ErrorOr socket_for_client_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client_result.value().GetRemoteDevice().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); // Expect an invalid socket from stopping during the first attempt to // connect, because `Connect` returned immediately when it checked for @@ -401,21 +403,22 @@ TEST_P(BluetoothClassicTest, CanCancelDuringConnect) { accept_latch.CountDown(); })); CancellationFlag flag; - BluetoothSocket socket_for_client = + ErrorOr socket_for_client_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client_result.value().GetRemoteDevice().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); // Since the flag was cancelled during the initial `AttemptToConnect`, // except only one attempt instead of the usual three, because the @@ -468,7 +471,7 @@ TEST_P(BluetoothClassicTest, CanCancelDuringConnect_MultipleEndpoints) { accept_latch.CountDown(); })); CancellationFlag flag; - BluetoothSocket socket_for_client1 = + ErrorOr socket_for_client1_result = bt_client.Connect(discovered_device, std::string(kServiceId1), &flag); // Simulate the flag being cancelled during connection attempt to a different @@ -485,7 +488,7 @@ TEST_P(BluetoothClassicTest, CanCancelDuringConnect_MultipleEndpoints) { })); CancellationFlag flag2; - BluetoothSocket socket_for_client2 = + ErrorOr socket_for_client2_result = bt_client.Connect(discovered_device, std::string(kServiceId2), &flag2); // If FeatureFlag is disabled, Cancelled is false as no-op. @@ -495,17 +498,20 @@ TEST_P(BluetoothClassicTest, CanCancelDuringConnect_MultipleEndpoints) { EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId2))); EXPECT_TRUE(socket_for_server1.IsValid()); EXPECT_TRUE(socket_for_server2.IsValid()); - EXPECT_TRUE(socket_for_client1.IsValid()); - EXPECT_TRUE(socket_for_client2.IsValid()); + EXPECT_TRUE(socket_for_client1_result.has_value()); + EXPECT_TRUE(socket_for_client1_result.value().IsValid()); + EXPECT_TRUE(socket_for_client2_result.has_value()); + EXPECT_TRUE(socket_for_client2_result.value().IsValid()); EXPECT_TRUE(socket_for_server1.GetRemoteDevice().IsValid()); EXPECT_TRUE(socket_for_server2.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client1.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client2.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client1_result.value().GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client2_result.value().GetRemoteDevice().IsValid()); } else { EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId1))); EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceId2))); - EXPECT_TRUE(socket_for_client1.IsValid()); - EXPECT_FALSE(socket_for_client2.IsValid()); + EXPECT_TRUE(socket_for_client1_result.has_value()); + EXPECT_TRUE(socket_for_client1_result.value().IsValid()); + EXPECT_TRUE(socket_for_client2_result.has_error()); // Since the flag was cancelled during the initial `AttemptToConnect`, // except only one attempt instead of the usual three, because the diff --git a/connections/implementation/mediums/wifi_lan.cc b/connections/implementation/mediums/wifi_lan.cc index d9458437d4..e36de309c9 100644 --- a/connections/implementation/mediums/wifi_lan.cc +++ b/connections/implementation/mediums/wifi_lan.cc @@ -28,6 +28,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/implementation/wifi_utils.h" #include "internal/platform/logging.h" #include "internal/platform/mutex_lock.h" @@ -41,6 +42,7 @@ namespace connections { namespace { using MultiplexSocket = mediums::multiplex::MultiplexSocket; +using location::nearby::proto::connections::OperationResultCode; } // namespace WifiLan::~WifiLan() { @@ -80,27 +82,27 @@ bool WifiLan::IsAvailable() const { bool WifiLan::IsAvailableLocked() const { return medium_.IsValid(); } -bool WifiLan::StartAdvertising(const std::string& service_id, - NsdServiceInfo& nsd_service_info) { +ErrorOr WifiLan::StartAdvertising(const std::string& service_id, + NsdServiceInfo& nsd_service_info) { MutexLock lock(&mutex_); if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't turn on WifiLan advertising. WifiLan is not available."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_LAN_NOT_AVAILABLE)}; } if (!nsd_service_info.IsValid()) { NEARBY_LOGS(INFO) << "Refusing to turn on WifiLan advertising. nsd_service_info is not " "valid."; - return false; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_NSD_NOT_AVAILABLE)}; } if (IsAdvertisingLocked(service_id)) { NEARBY_LOGS(INFO) << "Failed to WifiLan advertise because we're already advertising."; - return false; + return {Error(OperationResultCode::CLIENT_WIFI_LAN_DUPLICATE_ADVERTISING)}; } if (!IsAcceptingConnectionsLocked(service_id)) { @@ -110,7 +112,8 @@ bool WifiLan::StartAdvertising(const std::string& service_id, << ", service_name=" << nsd_service_info.GetServiceName() << ", service_id=" << service_id << ". Should accept connections before advertising."; - return false; + return {Error(OperationResultCode:: + CLIENT_DUPLICATE_ACCEPTING_LAN_CONNECTION_REQUEST)}; } nsd_service_info.SetServiceType(GenerateServiceType(service_id)); @@ -125,7 +128,8 @@ bool WifiLan::StartAdvertising(const std::string& service_id, << &nsd_service_info << ", service_name=" << nsd_service_info.GetServiceName() << ", service_id=" << service_id; - return false; + return {Error( + OperationResultCode::CONNECTIVITY_WIFI_LAN_START_ADVERTISING_FAILURE)}; } NEARBY_LOGS(INFO) << "Turned on WifiLan advertising with nsd_service_info=" @@ -133,7 +137,7 @@ bool WifiLan::StartAdvertising(const std::string& service_id, << ", service_name=" << nsd_service_info.GetServiceName() << ", service_id=" << service_id; advertising_info_.Add(service_id, std::move(nsd_service_info)); - return true; + return {true}; } bool WifiLan::StopAdvertising(const std::string& service_id) { @@ -165,27 +169,29 @@ bool WifiLan::IsAdvertisingLocked(const std::string& service_id) { return advertising_info_.Existed(service_id); } -bool WifiLan::StartDiscovery(const std::string& service_id, - DiscoveredServiceCallback callback) { +ErrorOr WifiLan::StartDiscovery(const std::string& service_id, + DiscoveredServiceCallback callback) { MutexLock lock(&mutex_); if (service_id.empty()) { NEARBY_LOGS(INFO) << "Refusing to start WifiLan discovering with empty service_id."; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't discover WifiLan services because WifiLan isn't available."; - return false; + return {Error( + OperationResultCode::MEDIUM_UNAVAILABLE_WIFI_AWARE_NOT_AVAILABLE)}; } if (IsDiscoveringLocked(service_id)) { NEARBY_LOGS(INFO) << "Refusing to start discovery of WifiLan services because another " "discovery is already in-progress."; - return false; + return {Error(OperationResultCode::CLIENT_WIFI_LAN_DUPLICATE_DISCOVERING)}; } std::string service_type = GenerateServiceType(service_id); @@ -193,14 +199,15 @@ bool WifiLan::StartDiscovery(const std::string& service_id, medium_.StartDiscovery(service_id, service_type, std::move(callback)); if (!ret) { NEARBY_LOGS(INFO) << "Failed to start discovery of WifiLan services."; - return false; + return {Error( + OperationResultCode::CONNECTIVITY_WIFI_LAN_START_DISCOVERY_FAILURE)}; } NEARBY_LOGS(INFO) << "Turned on WifiLan discovering with service_id=" << service_id; // Mark the fact that we're currently performing a WifiLan discovering. discovering_info_.Add(service_id); - return true; + return {true}; } bool WifiLan::StopDiscovery(const std::string& service_id) { @@ -230,21 +237,23 @@ bool WifiLan::IsDiscoveringLocked(const std::string& service_id) { return discovering_info_.Existed(service_id); } -bool WifiLan::StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) { +ErrorOr WifiLan::StartAcceptingConnections( + const std::string& service_id, AcceptedConnectionCallback callback) { MutexLock lock(&mutex_); if (service_id.empty()) { NEARBY_LOGS(INFO) << "Refusing to start accepting WifiLan connections; " "service_id is empty."; - return false; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't start accepting WifiLan connections [service_id=" << service_id << "]; WifiLan not available."; - return false; + return {Error( + OperationResultCode::MEDIUM_UNAVAILABLE_WIFI_AWARE_NOT_AVAILABLE)}; } if (IsAcceptingConnectionsLocked(service_id)) { @@ -252,7 +261,8 @@ bool WifiLan::StartAcceptingConnections(const std::string& service_id, << "Refusing to start accepting WifiLan connections [service=" << service_id << "]; WifiLan server is already in-progress with the same name."; - return false; + return {Error(OperationResultCode:: + CLIENT_DUPLICATE_ACCEPTING_LAN_CONNECTION_REQUEST)}; } auto port_range = medium_.GetDynamicPortRange(); @@ -270,7 +280,8 @@ bool WifiLan::StartAcceptingConnections(const std::string& service_id, NEARBY_LOGS(INFO) << "Failed to start accepting WifiLan connections for service_id=" << service_id; - return false; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_WIFI_LAN_SERVER_SOCKET_CREATION)}; } // Mark the fact that there's an in-progress WifiLan server accepting @@ -354,13 +365,13 @@ bool WifiLan::StartAcceptingConnections(const std::string& service_id, } } if (callback && !callback_called) { - NEARBY_LOGS(INFO) << "Call back triggered for physical socket."; + NEARBY_LOGS(INFO) << "Call back triggered for physical socket."; callback(service_id, std::move(client_socket)); } } }); - return true; + return {true}; } bool WifiLan::StopAcceptingConnections(const std::string& service_id) { @@ -417,9 +428,9 @@ bool WifiLan::IsAcceptingConnectionsLocked(const std::string& service_id) { return server_sockets_.find(service_id) != server_sockets_.end(); } -WifiLanSocket WifiLan::Connect(const std::string& service_id, - const NsdServiceInfo& service_info, - CancellationFlag* cancellation_flag) { +ErrorOr WifiLan::Connect(const std::string& service_id, + const NsdServiceInfo& service_info, + CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); // Socket to return. To allow for NRVO to work, it has to be a single object. WifiLanSocket socket; @@ -427,18 +438,20 @@ WifiLanSocket WifiLan::Connect(const std::string& service_id, if (service_id.empty()) { NEARBY_LOGS(INFO) << "Refusing to create client WifiLan socket because " "service_id is empty."; - return socket; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't create client WifiLan socket [service_id=" << service_id << "]; WifiLan isn't available."; - return socket; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_LAN_NOT_AVAILABLE)}; } if (cancellation_flag->Cancelled()) { NEARBY_LOGS(INFO) << "Can't create client WifiLan socket due to cancel."; - return socket; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_LAN_OUTGOING_CONNECTION)}; } ExceptionOr virtual_socket = @@ -451,7 +464,8 @@ WifiLanSocket WifiLan::Connect(const std::string& service_id, if (!socket.IsValid()) { NEARBY_LOGS(INFO) << "Failed to Connect via WifiLan [service_id=" << service_id << "]"; - return socket; + return {Error( + OperationResultCode::CONNECTIVITY_LAN_CLIENT_SOCKET_CREATION_FAILURE)}; } else { ExceptionOr virtual_socket = CreateOutgoingMultiplexSocketLocked(socket, service_id, @@ -469,9 +483,9 @@ WifiLanSocket WifiLan::Connect(const std::string& service_id, return socket; } -WifiLanSocket WifiLan::Connect(const std::string& service_id, - const std::string& ip_address, int port, - CancellationFlag* cancellation_flag) { +ErrorOr WifiLan::Connect(const std::string& service_id, + const std::string& ip_address, int port, + CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); // Socket to return. To allow for NRVO to work, it has to be a single object. WifiLanSocket socket; @@ -479,18 +493,20 @@ WifiLanSocket WifiLan::Connect(const std::string& service_id, if (service_id.empty()) { NEARBY_LOGS(INFO) << "Refusing to create client WifiLan socket because " "service_id is empty."; - return socket; + // TODO(edwinwu): Modify new OperationResultCode + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } if (!IsAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't create client WifiLan socket [service_id=" << service_id << "]; WifiLan isn't available."; - return socket; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_LAN_NOT_AVAILABLE)}; } if (cancellation_flag->Cancelled()) { NEARBY_LOGS(INFO) << "Can't create client WifiLan socket due to cancel."; - return socket; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_LAN_OUTGOING_CONNECTION)}; } ExceptionOr virtual_socket = @@ -503,7 +519,8 @@ WifiLanSocket WifiLan::Connect(const std::string& service_id, if (!socket.IsValid()) { NEARBY_LOGS(INFO) << "Failed to Connect via WifiLan [service_id=" << service_id << "]"; - return socket; + return {Error( + OperationResultCode::CONNECTIVITY_LAN_CLIENT_SOCKET_CREATION_FAILURE)}; } else { ExceptionOr virtual_socket = CreateOutgoingMultiplexSocketLocked(socket, service_id, ip_address); @@ -575,8 +592,7 @@ ExceptionOr WifiLan::CreateOutgoingMultiplexSocketLocked( } NEARBY_LOGS(INFO) << "Multiplex socket created for ip_address: " << WifiUtils::GetHumanReadableIpAddress(ip_address); - multiplex_sockets_.emplace(ip_address, - multiplex_socket); + multiplex_sockets_.emplace(ip_address, multiplex_socket); return ExceptionOr(*wlan_socket); } return ExceptionOr(Exception::kFailed); diff --git a/connections/implementation/mediums/wifi_lan.h b/connections/implementation/mediums/wifi_lan.h index 37f95d9f25..32345f2824 100644 --- a/connections/implementation/mediums/wifi_lan.h +++ b/connections/implementation/mediums/wifi_lan.h @@ -28,6 +28,7 @@ #include "internal/flags/nearby_flags.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/multi_thread_executor.h" #include "internal/platform/mutex.h" #include "internal/platform/nsd_service_info.h" @@ -53,8 +54,8 @@ class WifiLan { // Sets custom service info name, endpoint info name in NsdServiceInfo and // then enables WifiLan advertising. // Returns true, if NsdServiceInfo is successfully set, and false otherwise. - bool StartAdvertising(const std::string& service_id, - NsdServiceInfo& nsd_service_info) + ErrorOr StartAdvertising(const std::string& service_id, + NsdServiceInfo& nsd_service_info) ABSL_LOCKS_EXCLUDED(mutex_); // Disables WifiLan advertising. @@ -68,8 +69,8 @@ class WifiLan { // Enables WifiLan discovery. Will report any discoverable services // through a callback. // Returns true, if discovery was enabled, false otherwise. - bool StartDiscovery(const std::string& service_id, - DiscoveredServiceCallback callback) + ErrorOr StartDiscovery(const std::string& service_id, + DiscoveredServiceCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Disables WifiLan discovery. @@ -79,8 +80,8 @@ class WifiLan { // Starts a worker thread, creates a WifiLan socket, associates it with a // service id. - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) + ErrorOr StartAcceptingConnections(const std::string& service_id, + AcceptedConnectionCallback callback) ABSL_LOCKS_EXCLUDED(mutex_); // Closes socket corresponding to a service id. @@ -94,17 +95,17 @@ class WifiLan { // another service with StartAcceptingConnections() using the same service_id. // Blocks until connection is established, or server-side is terminated. // Returns socket instance. On success, WifiLanSocket.IsValid() return true. - WifiLanSocket Connect(const std::string& service_id, - const NsdServiceInfo& service_info, - CancellationFlag* cancellation_flag) + ErrorOr Connect(const std::string& service_id, + const NsdServiceInfo& service_info, + CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); // Establishes connection to WifiLan service by ip address and port for // bandwidth upgradation. // Returns socket instance. On success, WifiLanSocket.IsValid() return true. - WifiLanSocket Connect(const std::string& service_id, - const std::string& ip_address, int port, - CancellationFlag* cancellation_flag) + ErrorOr Connect(const std::string& service_id, + const std::string& ip_address, int port, + CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); // Gets ip address + port for remote services on the network to identify and @@ -207,12 +208,10 @@ class WifiLan { // Whether the multiplex feature is enabled. bool is_multiplex_enabled_ = NearbyFlags::GetInstance().GetBoolFlag( - config_package_nearby::nearby_connections_feature:: - kEnableMultiplex); + config_package_nearby::nearby_connections_feature::kEnableMultiplex); // A map of IpAddress -> MultiplexSocket. - absl::flat_hash_map + absl::flat_hash_map multiplex_sockets_ ABSL_GUARDED_BY(mutex_); }; diff --git a/connections/implementation/mediums/wifi_lan_test.cc b/connections/implementation/mediums/wifi_lan_test.cc index fa6649d127..77b8f59e48 100644 --- a/connections/implementation/mediums/wifi_lan_test.cc +++ b/connections/implementation/mediums/wifi_lan_test.cc @@ -17,20 +17,21 @@ #include #include -#include "gmock/gmock.h" -#include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" +#include "absl/time/time.h" #include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "internal/flags/nearby_flags.h" +#include "internal/platform/base64_utils.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" +#include "internal/platform/feature_flags.h" #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" #include "internal/platform/nsd_service_info.h" #include "internal/platform/single_thread_executor.h" #include "internal/platform/wifi_lan.h" -#include "internal/platform/base64_utils.h" namespace nearby { namespace connections { @@ -102,13 +103,14 @@ TEST_P(WifiLanTest, CanConnect) { ASSERT_TRUE(discovered_service_info.IsValid()); CancellationFlag flag; - WifiLanSocket socket_for_client = + ErrorOr socket_for_client_result = wifi_lan_client.Connect(service_id, discovered_service_info, &flag); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); env_.Stop(); } @@ -145,26 +147,28 @@ TEST_P(WifiLanTest, CanConnectWithMultiplex) { WifiLanSocket socket_for_client; SingleThreadExecutor client_executor; client_executor.Execute([&]() { - NsdServiceInfo discovered_service_info; - wifi_lan_client.StartDiscovery( - service_id, - { - .service_discovered_cb = - [&discovered_latch, &discovered_service_info]( - NsdServiceInfo service_info, const std::string& service_id) { - NEARBY_LOGS(INFO) - << "Discovered service_info=" << &service_info; - discovered_service_info = service_info; - discovered_latch.CountDown(); - }, - }); - discovered_latch.Await(kWaitDuration).result(); - ASSERT_TRUE(discovered_service_info.IsValid()); - - CancellationFlag flag; - socket_for_client = - wifi_lan_client.Connect(service_id, discovered_service_info, &flag); - Base64Utils::WriteInt(&socket_for_client.GetOutputStream(), 4); + NsdServiceInfo discovered_service_info; + wifi_lan_client.StartDiscovery( + service_id, { + .service_discovered_cb = + [&discovered_latch, &discovered_service_info]( + NsdServiceInfo service_info, + const std::string& service_id) { + NEARBY_LOGS(INFO) << "Discovered service_info=" + << &service_info; + discovered_service_info = service_info; + discovered_latch.CountDown(); + }, + }); + discovered_latch.Await(kWaitDuration).result(); + ASSERT_TRUE(discovered_service_info.IsValid()); + + CancellationFlag flag; + ErrorOr socket_for_client_result = + wifi_lan_client.Connect(service_id, discovered_service_info, &flag); + socket_for_client = std::move(socket_for_client_result.value()); + Base64Utils::WriteInt(&socket_for_client_result.value().GetOutputStream(), + 4); }); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); @@ -219,7 +223,7 @@ TEST_P(WifiLanTest, CanCancelConnect) { ASSERT_TRUE(discovered_service_info.IsValid()); CancellationFlag flag(true); - WifiLanSocket socket_for_client = + ErrorOr socket_for_client_result = wifi_lan_client.Connect(service_id, discovered_service_info, &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { @@ -227,13 +231,14 @@ TEST_P(WifiLanTest, CanCancelConnect) { EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_value()); + EXPECT_TRUE(socket_for_client_result.value().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_client_result.has_error()); } env_.Stop(); } diff --git a/connections/implementation/p2p_cluster_pcp_handler.cc b/connections/implementation/p2p_cluster_pcp_handler.cc index 290f9183cc..c9d9afe55e 100644 --- a/connections/implementation/p2p_cluster_pcp_handler.cc +++ b/connections/implementation/p2p_cluster_pcp_handler.cc @@ -58,6 +58,7 @@ #include "internal/platform/bluetooth_adapter.h" #include "internal/platform/bluetooth_classic.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/implementation/platform.h" #include "internal/platform/logging.h" #include "internal/platform/nsd_service_info.h" @@ -69,6 +70,17 @@ namespace nearby { namespace connections { +namespace { +using ::location::nearby::analytics::proto::ConnectionsLog; +using ::location::nearby::proto::connections::OperationResultCode; +using ::location::nearby::proto::connections::Medium::BLE; +using ::location::nearby::proto::connections::Medium::BLUETOOTH; +using ::location::nearby::proto::connections::Medium::UNKNOWN_MEDIUM; +using ::location::nearby::proto::connections::Medium::WEB_RTC; +using ::location::nearby::proto::connections::Medium::WIFI_LAN; + +} // namespace + ByteArray P2pClusterPcpHandler::GenerateHash(const std::string& source, size_t size) { return Utils::Sha256Hash(source, size); @@ -111,60 +123,73 @@ P2pClusterPcpHandler::~P2pClusterPcpHandler() { std::vector P2pClusterPcpHandler::GetConnectionMediumsByPriority() { std::vector mediums; if (wifi_lan_medium_.IsAvailable()) { - mediums.push_back(location::nearby::proto::connections::WIFI_LAN); + mediums.push_back(WIFI_LAN); } if (webrtc_medium_.IsAvailable()) { - mediums.push_back(location::nearby::proto::connections::WEB_RTC); + mediums.push_back(WEB_RTC); } if (bluetooth_medium_.IsAvailable()) { - mediums.push_back(location::nearby::proto::connections::BLUETOOTH); + mediums.push_back(BLUETOOTH); } if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableBleV2)) { if (ble_v2_medium_.IsAvailable()) { - mediums.push_back(location::nearby::proto::connections::BLE); + mediums.push_back(BLE); } } else { if (ble_medium_.IsAvailable()) { - mediums.push_back(location::nearby::proto::connections::BLE); + mediums.push_back(BLE); } } return mediums; } -Medium P2pClusterPcpHandler::GetDefaultUpgradeMedium() { - return location::nearby::proto::connections::WIFI_LAN; -} +Medium P2pClusterPcpHandler::GetDefaultUpgradeMedium() { return WIFI_LAN; } BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, const AdvertisingOptions& advertising_options) { std::vector mediums_started_successfully; + std::vector + operation_result_with_mediums; WebRtcState web_rtc_state{WebRtcState::kUnconnectable}; if (advertising_options.allowed.wifi_lan) { - Medium wifi_lan_medium = + ErrorOr wifi_lan_result = StartWifiLanAdvertising(client, service_id, local_endpoint_id, local_endpoint_info, web_rtc_state); - if (wifi_lan_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + Medium wifi_lan_medium = UNKNOWN_MEDIUM; + if (wifi_lan_result.has_value()) { + wifi_lan_medium = wifi_lan_result.value(); + } + if (wifi_lan_medium != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartAdvertisingImpl: WifiLan added"; mediums_started_successfully.push_back(wifi_lan_medium); } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, /*update_index=*/0, + wifi_lan_result.has_error() + ? wifi_lan_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } if (advertising_options.allowed.bluetooth) { const ByteArray bluetooth_hash = GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); - Medium bluetooth_medium = StartBluetoothAdvertising( + ErrorOr bluetooth_result = StartBluetoothAdvertising( client, service_id, bluetooth_hash, local_endpoint_id, local_endpoint_info, web_rtc_state); - if (bluetooth_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + Medium bluetooth_medium = UNKNOWN_MEDIUM; + if (bluetooth_result.has_value()) { + bluetooth_medium = bluetooth_result.value(); + } + if (bluetooth_medium != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartAdvertisingImpl: BT started"; @@ -218,38 +243,55 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( bluetooth_classic_advertiser_client_id_ = client->GetClientId(); } } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, + /*update_index=*/0, + bluetooth_result.has_error() + ? bluetooth_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } if (advertising_options.allowed.ble) { + ErrorOr ble_result = {Error(OperationResultCode::DETAIL_UNKNOWN)}; if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableBleV2)) { - Medium ble_v2_medium = StartBleV2Advertising( - client, service_id, local_endpoint_id, local_endpoint_info, - advertising_options, web_rtc_state); - if (ble_v2_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ble_result = StartBleV2Advertising(client, service_id, local_endpoint_id, + local_endpoint_info, + advertising_options, web_rtc_state); + if (ble_result.has_value() && ble_result.value() != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; - mediums_started_successfully.push_back(ble_v2_medium); + mediums_started_successfully.push_back(ble_result.value()); } } else { - Medium ble_medium = StartBleAdvertising( - client, service_id, local_endpoint_id, local_endpoint_info, - advertising_options, web_rtc_state); - if (ble_medium != location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ble_result = StartBleAdvertising(client, service_id, local_endpoint_id, + local_endpoint_info, advertising_options, + web_rtc_state); + if (ble_result.has_value() && ble_result.value() != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; - mediums_started_successfully.push_back(ble_medium); + mediums_started_successfully.push_back(ble_result.value()); } } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client, BLE, /*update_index=*/0, + ble_result.has_error() + ? ble_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); } if (mediums_started_successfully.empty()) { NEARBY_LOGS(ERROR) << "Failed StartAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) << ") for client=" << client->GetClientId(); + // TODO(edwinwu): Modify the status instead of kBluetoothError return { .status = {Status::kBluetoothError}, + .operation_result_with_mediums = + std::move(operation_result_with_mediums), }; } @@ -260,6 +302,7 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( return { .status = {Status::kSuccess}, .mediums = std::move(mediums_started_successfully), + .operation_result_with_mediums = std::move(operation_result_with_mediums), }; } @@ -378,12 +421,12 @@ void P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler( << absl::BytesToHexString(device_name.GetEndpointInfo().data()) << ")."; OnEndpointFound( - client, std::make_shared(BluetoothEndpoint{ - {device_name.GetEndpointId(), - device_name.GetEndpointInfo(), service_id, - Medium::BLUETOOTH, device_name.GetWebRtcState()}, - device, - })); + client, + std::make_shared(BluetoothEndpoint{ + {device_name.GetEndpointId(), device_name.GetEndpointInfo(), + service_id, BLUETOOTH, device_name.GetWebRtcState()}, + device, + })); }); } @@ -392,83 +435,85 @@ void P2pClusterPcpHandler::BluetoothNameChangedHandler( BluetoothDevice device) { RunOnPcpHandlerThread( "p2p-bt-name-changed", - [this, client, service_id, device]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!device.IsValid()) { - NEARBY_LOGS(WARNING) << "BluetoothNameChangedHandler: Skipping the " - "invalid Bluetooth device"; - return; - } + [this, client, service_id, device]() + RUN_ON_PCP_HANDLER_THREAD() { + // Make sure we are still discovering before proceeding. + if (!device.IsValid()) { + NEARBY_LOGS(WARNING) + << "BluetoothNameChangedHandler: Skipping the " + "invalid Bluetooth device"; + return; + } - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) - << "Ignoring lost BluetoothDevice " << device.GetName() - << " because Connections is no longer discovering."; - return; - } + if (!client->IsDiscovering()) { + NEARBY_LOGS(WARNING) + << "Ignoring lost BluetoothDevice " << device.GetName() + << " because Connections is no longer discovering."; + return; + } - // Parse the Bluetooth device name. - const std::string device_name_string = device.GetName(); - BluetoothDeviceName device_name(device_name_string); - NEARBY_LOGS(INFO) << "BT discovery handler (CHANGED) [client_id=" - << client->GetClientId() - << ", service_id=" << service_id - << "]: processing new name " << device_name_string; - - // By this point, the BluetoothDevice passed to us has a different - // name than what we may have discovered before. We need to iterate - // over the found BluetoothEndpoints and compare their addresses to - // see the devices are the same. We are not guaranteed to discover a - // match, since the old name may not have been formatted for Nearby - // Connections. - for (auto endpoint : GetDiscoveredEndpoints(Medium::BLUETOOTH)) { - BluetoothEndpoint* bluetoothEndpoint = - static_cast(endpoint); - NEARBY_LOGS(INFO) - << "BT discovery handler (CHANGED) [client_id=" - << client->GetClientId() << ", service_id=" << service_id - << "]: comparing MAC addresses with existing endpoint " - << bluetoothEndpoint->bluetooth_device.GetName() - << ". They have MAC address " - << bluetoothEndpoint->bluetooth_device.GetMacAddress() - << " and the new endpoint has MAC address " - << device.GetMacAddress(); - if (bluetoothEndpoint->bluetooth_device.GetMacAddress() == - device.GetMacAddress()) { - // Report the BluetoothEndpoint as lost to the client. - NEARBY_LOGS(INFO) << "Reporting lost BluetoothDevice " - << bluetoothEndpoint->bluetooth_device.GetName() - << ", due to device name change."; - OnEndpointLost(client, *endpoint); - break; - } - } + // Parse the Bluetooth device name. + const std::string device_name_string = device.GetName(); + BluetoothDeviceName device_name(device_name_string); + NEARBY_LOGS(INFO) + << "BT discovery handler (CHANGED) [client_id=" + << client->GetClientId() << ", service_id=" << service_id + << "]: processing new name " << device_name_string; + + // By this point, the BluetoothDevice passed to us has a different + // name than what we may have discovered before. We need to iterate + // over the found BluetoothEndpoints and compare their addresses to + // see the devices are the same. We are not guaranteed to discover a + // match, since the old name may not have been formatted for Nearby + // Connections. + for (auto endpoint : GetDiscoveredEndpoints(BLUETOOTH)) { + BluetoothEndpoint* bluetoothEndpoint = + static_cast(endpoint); + NEARBY_LOGS(INFO) + << "BT discovery handler (CHANGED) [client_id=" + << client->GetClientId() << ", service_id=" << service_id + << "]: comparing MAC addresses with existing endpoint " + << bluetoothEndpoint->bluetooth_device.GetName() + << ". They have MAC address " + << bluetoothEndpoint->bluetooth_device.GetMacAddress() + << " and the new endpoint has MAC address " + << device.GetMacAddress(); + if (bluetoothEndpoint->bluetooth_device.GetMacAddress() == + device.GetMacAddress()) { + // Report the BluetoothEndpoint as lost to the client. + NEARBY_LOGS(INFO) + << "Reporting lost BluetoothDevice " + << bluetoothEndpoint->bluetooth_device.GetName() + << ", due to device name change."; + OnEndpointLost(client, *endpoint); + break; + } + } - // Make sure the Bluetooth device name points to a valid - // endpoint we're discovering. - if (!IsRecognizedBluetoothEndpoint(device_name_string, service_id, - device_name)) { - NEARBY_LOGS(INFO) << "Found unrecognized BluetoothDeviceName " - << device_name_string; - return; - } + // Make sure the Bluetooth device name points to a valid + // endpoint we're discovering. + if (!IsRecognizedBluetoothEndpoint(device_name_string, service_id, + device_name)) { + NEARBY_LOGS(INFO) << "Found unrecognized BluetoothDeviceName " + << device_name_string; + return; + } - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) << "Found BluetoothDeviceName " << device_name_string - << " (with endpoint_id=" - << device_name.GetEndpointId() - << " and endpoint_info=" - << absl::BytesToHexString( - device_name.GetEndpointInfo().data()) - << ")."; - OnEndpointFound( - client, - std::make_shared(BluetoothEndpoint{ - {device_name.GetEndpointId(), device_name.GetEndpointInfo(), - service_id, Medium::BLUETOOTH, device_name.GetWebRtcState()}, - device, - })); - }); + // Report the discovered endpoint to the client. + NEARBY_LOGS(INFO) + << "Found BluetoothDeviceName " << device_name_string + << " (with endpoint_id=" << device_name.GetEndpointId() + << " and endpoint_info=" + << absl::BytesToHexString(device_name.GetEndpointInfo().data()) + << ")."; + OnEndpointFound( + client, + std::make_shared(BluetoothEndpoint{ + {device_name.GetEndpointId(), device_name.GetEndpointInfo(), + service_id, BLUETOOTH, device_name.GetWebRtcState()}, + device, + })); + }); } void P2pClusterPcpHandler::BluetoothDeviceLostHandler( @@ -507,7 +552,7 @@ void P2pClusterPcpHandler::BluetoothDeviceLostHandler( << device_name_string; OnEndpointLost(client, DiscoveredEndpoint{device_name.GetEndpointId(), device_name.GetEndpointInfo(), - service_id, Medium::BLUETOOTH, + service_id, BLUETOOTH, WebRtcState::kUndefined}); }); } @@ -579,8 +624,7 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( BleEndpointState(advertisement.GetEndpointId(), advertisement.GetEndpointInfo())); - StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), - Medium::BLE); + StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), BLE); // Report the discovered endpoint to the client. NEARBY_LOGS(INFO) << "Found BleAdvertisement " @@ -595,7 +639,7 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( client, std::make_shared(BleEndpoint{ {advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), - service_id, Medium::BLE, advertisement.GetWebRtcState()}, + service_id, BLE, advertisement.GetWebRtcState()}, peripheral, })); @@ -618,15 +662,14 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( return; } - StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), - Medium::BLUETOOTH); + StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), BLUETOOTH); OnEndpointFound(client, std::make_shared(BluetoothEndpoint{ { advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), service_id, - Medium::BLUETOOTH, + BLUETOOTH, advertisement.GetWebRtcState(), }, remote_bluetooth_device, @@ -667,7 +710,7 @@ void P2pClusterPcpHandler::BlePeripheralLostHandler( ble_endpoint_state.endpoint_id, ble_endpoint_state.endpoint_info, service_id, - Medium::BLE, + BLE, WebRtcState::kUndefined, }); } @@ -721,7 +764,6 @@ void P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler( ClientProxy* client, BleV2Peripheral peripheral, const std::string& service_id, const ByteArray& advertisement_bytes, bool fast_advertisement) { - // TODO(edwinwu): Move the lambda to a named function. RunOnPcpHandlerThread( "p2p-ble-peripheral-discovered", [this, client, peripheral = std::move(peripheral), service_id, @@ -771,13 +813,12 @@ void P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler( << absl::BytesToHexString( advertisement.GetEndpointInfo().data()) << ")."; - StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), - Medium::BLE); + StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), BLE); OnEndpointFound( client, std::make_shared(BleV2Endpoint{ {advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), - service_id, Medium::BLE, advertisement.GetWebRtcState()}, + service_id, BLE, advertisement.GetWebRtcState()}, std::move(peripheral), })); @@ -802,8 +843,7 @@ void P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler( ble_endpoint_state.bt = true; found_endpoints_in_ble_discover_cb_[peripheral_id] = ble_endpoint_state; - StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), - Medium::BLUETOOTH); + StopEndpointLostByMediumAlarm(advertisement.GetEndpointId(), BLUETOOTH); OnEndpointFound(client, std::make_shared(BluetoothEndpoint{ @@ -811,7 +851,7 @@ void P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler( advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), service_id, - Medium::BLUETOOTH, + BLUETOOTH, advertisement.GetWebRtcState(), }, remote_bluetooth_device, @@ -872,7 +912,7 @@ void P2pClusterPcpHandler::BleV2PeripheralLostHandler( advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), service_id, - Medium::BLE, + BLE, WebRtcState::kUndefined, }); } @@ -889,7 +929,7 @@ void P2pClusterPcpHandler::BleV2PeripheralLostHandler( advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), service_id, - Medium::BLUETOOTH, + BLUETOOTH, WebRtcState::kUndefined, }); } @@ -1047,14 +1087,14 @@ void P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler( wifi_lan_service_info.GetEndpointInfo().data()) << ")."; StopEndpointLostByMediumAlarm(wifi_lan_service_info.GetEndpointId(), - Medium::WIFI_LAN); + WIFI_LAN); OnEndpointFound(client, std::make_shared(WifiLanEndpoint{ { wifi_lan_service_info.GetEndpointId(), wifi_lan_service_info.GetEndpointInfo(), service_id, - Medium::WIFI_LAN, + WIFI_LAN, wifi_lan_service_info.GetWebRtcState(), }, service_info, @@ -1100,7 +1140,7 @@ void P2pClusterPcpHandler::WifiLanServiceLostHandler( wifi_lan_service_info.GetEndpointId(), wifi_lan_service_info.GetEndpointInfo(), service_id, - Medium::WIFI_LAN, + WIFI_LAN, WebRtcState::kUndefined, }); }); @@ -1117,56 +1157,94 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( } std::vector mediums_started_successfully; + std::vector + operation_result_with_mediums; if (discovery_options.allowed.wifi_lan) { - Medium wifi_lan_medium = StartWifiLanDiscovery(client, service_id); - if (wifi_lan_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ErrorOr wifi_lan_result = StartWifiLanDiscovery(client, service_id); + Medium wifi_lan_medium = UNKNOWN_MEDIUM; + if (wifi_lan_result.has_value()) { + wifi_lan_medium = wifi_lan_result.value(); + } + if (wifi_lan_medium != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartDiscoveryImpl: WifiLan added"; mediums_started_successfully.push_back(wifi_lan_medium); } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, + /*update_index=*/0, + wifi_lan_result.has_error() + ? wifi_lan_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } if (discovery_options.allowed.ble) { + ErrorOr ble_result = {Error(OperationResultCode::DETAIL_UNKNOWN)}; if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableBleV2)) { - Medium ble_v2_medium = - StartBleV2Scanning(client, service_id, discovery_options); - if (ble_v2_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ble_result = StartBleV2Scanning(client, service_id, discovery_options); + Medium ble_v2_medium = UNKNOWN_MEDIUM; + if (ble_result.has_value()) { + ble_v2_medium = ble_result.value(); + } + if (ble_v2_medium != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble v2 added."; + << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble v2 added"; mediums_started_successfully.push_back(ble_v2_medium); } } else { - Medium ble_medium = + ble_result = StartBleScanning(client, service_id, discovery_options.fast_advertisement_service_uuid); - if (ble_medium != location::nearby::proto::connections::UNKNOWN_MEDIUM) { + Medium ble_medium = UNKNOWN_MEDIUM; + if (ble_result.has_value()) { + ble_medium = ble_result.value(); + } + if (ble_medium != UNKNOWN_MEDIUM) { NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added."; + << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added"; mediums_started_successfully.push_back(ble_medium); } } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client, BLE, + /*update_index=*/0, + ble_result.has_error() + ? ble_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } if (discovery_options.allowed.bluetooth) { if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: kDisableBluetoothClassicScanning)) { - StartBluetoothDiscoveryWithPause(client, service_id, discovery_options, - mediums_started_successfully); + StartBluetoothDiscoveryWithPause( + client, service_id, discovery_options, mediums_started_successfully, + operation_result_with_mediums, /*update_index=*/0); } else { - Medium bluetooth_medium = StartBluetoothDiscovery(client, service_id); - if (bluetooth_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ErrorOr bluetooth_result = + StartBluetoothDiscovery(client, service_id); + if (bluetooth_result.has_value()) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartDiscoveryImpl: BT added"; - mediums_started_successfully.push_back(bluetooth_medium); + mediums_started_successfully.push_back(*bluetooth_result); bluetooth_classic_client_id_to_service_id_map_.insert( {client->GetClientId(), service_id}); } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, + /*update_index=*/0, + bluetooth_result.has_error() + ? bluetooth_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } @@ -1176,14 +1254,18 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( << " because we couldn't scan on Bluetooth, BLE, or WifiLan for " "service_id=" << service_id; + // TODO(edwinwu): Modify the status instead of kBluetoothError return { .status = {Status::kBluetoothError}, + .operation_result_with_mediums = + std::move(operation_result_with_mediums), }; } return { .status = {Status::kSuccess}, .mediums = std::move(mediums_started_successfully), + .operation_result_with_mediums = std::move(operation_result_with_mediums), }; } @@ -1223,7 +1305,7 @@ Status P2pClusterPcpHandler::InjectEndpointImpl( const OutOfBandConnectionMetadata& metadata) { NEARBY_LOGS(INFO) << "InjectEndpoint."; // Bluetooth is the only supported out-of-band connection medium. - if (metadata.medium != Medium::BLUETOOTH) { + if (metadata.medium != BLUETOOTH) { NEARBY_LOGS(WARNING) << "InjectEndpointImpl: Only Bluetooth is supported."; return {Status::kError}; } @@ -1252,14 +1334,14 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl( }; } switch (endpoint->medium) { - case Medium::BLUETOOTH: { + case BLUETOOTH: { auto* bluetooth_endpoint = down_cast(endpoint); if (bluetooth_endpoint) { return BluetoothConnectImpl(client, bluetooth_endpoint); } break; } - case Medium::BLE: { + case BLE: { if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: kEnableBleV2)) { @@ -1276,14 +1358,14 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl( } break; } - case Medium::WIFI_LAN: { + case WIFI_LAN: { auto* wifi_lan_endpoint = down_cast(endpoint); if (wifi_lan_endpoint) { return WifiLanConnectImpl(client, wifi_lan_endpoint); } break; } - case Medium::WEB_RTC: { + case WEB_RTC: { break; } default: @@ -1301,20 +1383,32 @@ P2pClusterPcpHandler::StartListeningForIncomingConnectionsImpl( absl::string_view local_endpoint_id, v3::ConnectionListeningOptions options) { std::vector started_mediums; + std::vector + operation_result_with_mediums; + int update_index = + client_proxy->GetAnalyticsRecorder().GetNextAdvertisingUpdateIndex(); if (options.enable_bluetooth_listening && !bluetooth_medium_.IsAcceptingConnections(std::string(service_id))) { - if (!bluetooth_medium_.StartAcceptingConnections( + ErrorOr bluetooth_result = + bluetooth_medium_.StartAcceptingConnections( std::string(service_id), absl::bind_front( &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, this, client_proxy, local_endpoint_id, - options.listening_endpoint_type))) { + options.listening_endpoint_type)); + if (bluetooth_result.has_error()) { NEARBY_LOGS(WARNING) << "Failed to start listening for incoming connections on Bluetooth"; } else { - started_mediums.push_back( - location::nearby::proto::connections::BLUETOOTH); + started_mediums.push_back(BLUETOOTH); } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client_proxy, Medium::BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } // ble if (NearbyFlags::GetInstance().GetBoolFlag( @@ -1331,7 +1425,7 @@ P2pClusterPcpHandler::StartListeningForIncomingConnectionsImpl( NEARBY_LOGS(WARNING) << "Failed to start listening for incoming connections on ble_v2"; } else { - started_mediums.push_back(location::nearby::proto::connections::BLE); + started_mediums.push_back(BLE); } } } else { @@ -1347,23 +1441,31 @@ P2pClusterPcpHandler::StartListeningForIncomingConnectionsImpl( NEARBY_LOGS(WARNING) << "Failed to start listening for incoming connections on ble"; } else { - started_mediums.push_back(location::nearby::proto::connections::BLE); + started_mediums.push_back(BLE); } } } if (options.enable_wlan_listening && !wifi_lan_medium_.IsAcceptingConnections(std::string(service_id))) { - if (!wifi_lan_medium_.StartAcceptingConnections( - std::string(service_id), - absl::bind_front( - &P2pClusterPcpHandler::WifiLanConnectionAcceptedHandler, this, - client_proxy, local_endpoint_id, "", - options.listening_endpoint_type))) { + ErrorOr wifi_lan_result = wifi_lan_medium_.StartAcceptingConnections( + std::string(service_id), + absl::bind_front( + &P2pClusterPcpHandler::WifiLanConnectionAcceptedHandler, this, + client_proxy, local_endpoint_id, "", + options.listening_endpoint_type)); + if (wifi_lan_result.has_error()) { NEARBY_LOGS(WARNING) << "Failed to start listening for incoming connections on wifi_lan"; } else { - started_mediums.push_back(location::nearby::proto::connections::WIFI_LAN); + started_mediums.push_back(WIFI_LAN); } + std::unique_ptr + operation_result_with_medium = GetOperationResultWithMediumByResultCode( + client_proxy, Medium::BLUETOOTH, update_index, + wifi_lan_result.has_error() + ? wifi_lan_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } if (started_mediums.empty()) { NEARBY_LOGS(WARNING) << absl::StrFormat( @@ -1372,10 +1474,15 @@ P2pClusterPcpHandler::StartListeningForIncomingConnectionsImpl( client_proxy->GetClientId(), service_id); return StartOperationResult{ .status = {Status::kError}, + .operation_result_with_mediums = + std::move(operation_result_with_mediums), }; } return BasePcpHandler::StartOperationResult{ - .status = {Status::kSuccess}, .mediums = std::move(started_mediums)}; + .status = {Status::kSuccess}, + .mediums = std::move(started_mediums), + .operation_result_with_mediums = std::move(operation_result_with_mediums), + }; } void P2pClusterPcpHandler::StopListeningForIncomingConnectionsImpl( @@ -1426,8 +1533,7 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( AdvertisingOptions old_options = client->GetAdvertisingOptions(); bool needs_restart = old_options.low_power != advertising_options.low_power; // ble - if (NeedsToTurnOffAdvertisingMedium(Medium::BLE, old_options, - advertising_options) || + if (NeedsToTurnOffAdvertisingMedium(BLE, old_options, advertising_options) || needs_restart) { if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableBleV2)) { @@ -1439,14 +1545,14 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( } } // wifi lan - if (NeedsToTurnOffAdvertisingMedium(Medium::WIFI_LAN, old_options, + if (NeedsToTurnOffAdvertisingMedium(WIFI_LAN, old_options, advertising_options) || needs_restart) { mediums_->GetWifiLan().StopAdvertising(std::string(service_id)); mediums_->GetWifiLan().StopAcceptingConnections(std::string(service_id)); } // Bluetooth classic - if (NeedsToTurnOffAdvertisingMedium(Medium::BLUETOOTH, old_options, + if (NeedsToTurnOffAdvertisingMedium(BLUETOOTH, old_options, advertising_options) || needs_restart) { // BT classic equivalent for advertising. @@ -1470,6 +1576,10 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( // restart std::vector restarted_mediums; + std::vector + operation_result_with_mediums; + int update_index = + client->GetAnalyticsRecorder().GetNextAdvertisingUpdateIndex(); Status status = {Status::kSuccess}; WebRtcState web_rtc_state = webrtc_medium_.IsAvailable() ? WebRtcState::kConnectable @@ -1479,58 +1589,97 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( auto old_mediums = old_options.allowed; if (new_mediums.ble) { if (old_mediums.ble && !needs_restart) { - restarted_mediums.push_back(Medium::BLE); + restarted_mediums.push_back(BLE); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLE, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { + ErrorOr ble_result = {Error(OperationResultCode::DETAIL_UNKNOWN)}; if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: kEnableBleV2)) { - if (StartBleV2Advertising( - client, std::string(service_id), std::string(local_endpoint_id), - ByteArray(std::string(local_endpoint_info)), - advertising_options, web_rtc_state) != Medium::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::BLE); + ble_result = StartBleV2Advertising( + client, std::string(service_id), std::string(local_endpoint_id), + ByteArray(std::string(local_endpoint_info)), advertising_options, + web_rtc_state); + if (ble_result.has_value() && ble_result.value() != UNKNOWN_MEDIUM) { + restarted_mediums.push_back(BLE); } else { status = {Status::kBleError}; } } else { - if (StartBleAdvertising( - client, std::string(service_id), std::string(local_endpoint_id), - ByteArray(std::string(local_endpoint_info)), - advertising_options, web_rtc_state) != Medium::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::BLE); + ble_result = StartBleAdvertising( + client, std::string(service_id), std::string(local_endpoint_id), + ByteArray(std::string(local_endpoint_info)), advertising_options, + web_rtc_state); + if (ble_result.has_value() && ble_result.value() != UNKNOWN_MEDIUM) { + restarted_mediums.push_back(BLE); } else { status = {Status::kBleError}; } } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLE, update_index, + ble_result.has_error() + ? ble_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } // wifi lan if (new_mediums.wifi_lan && !advertising_options.low_power) { if (old_mediums.wifi_lan && !needs_restart) { - restarted_mediums.push_back(Medium::WIFI_LAN); + restarted_mediums.push_back(WIFI_LAN); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { - if (StartWifiLanAdvertising(client, std::string(service_id), - std::string(local_endpoint_id), - ByteArray(std::string(local_endpoint_info)), - web_rtc_state) != Medium::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::WIFI_LAN); + ErrorOr wifi_lan_result = StartWifiLanAdvertising( + client, std::string(service_id), std::string(local_endpoint_id), + ByteArray(std::string(local_endpoint_info)), web_rtc_state); + if (wifi_lan_result.has_value() && + wifi_lan_result.value() != UNKNOWN_MEDIUM) { + restarted_mediums.push_back(WIFI_LAN); } else { status = {Status::kWifiLanError}; } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, update_index, + wifi_lan_result.has_error() + ? wifi_lan_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } // bluetooth classic if (new_mediums.bluetooth && !advertising_options.low_power) { if (old_mediums.bluetooth && !needs_restart) { - restarted_mediums.push_back(Medium::BLUETOOTH); + restarted_mediums.push_back(BLUETOOTH); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { const ByteArray bluetooth_hash = GenerateHash( std::string(service_id), BluetoothDeviceName::kServiceIdHashLength); - if (StartBluetoothAdvertising(client, std::string(service_id), - bluetooth_hash, - std::string(local_endpoint_id), - ByteArray(std::string(local_endpoint_info)), - web_rtc_state) != Medium::UNKNOWN_MEDIUM) { + ErrorOr bluetooth_result = StartBluetoothAdvertising( + client, std::string(service_id), bluetooth_hash, + std::string(local_endpoint_id), + ByteArray(std::string(local_endpoint_info)), web_rtc_state); + if (bluetooth_result.has_value() && + bluetooth_result.value() != UNKNOWN_MEDIUM) { // TODO(hais): update this after ble_v2 refactor. if (api::ImplementationPlatform::GetCurrentOS() == api::OSName::kChromeOS && @@ -1545,7 +1694,7 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( "Ble legacy started advertising"; NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::" "UpdateAdvertisingOptionsImpl: BT added"; - restarted_mediums.push_back(Medium::BLUETOOTH); + restarted_mediums.push_back(BLUETOOTH); } else { NEARBY_LOGS(WARNING) << "P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl: BLE " @@ -1565,7 +1714,7 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( advertising_options.fast_advertisement_service_uuid)) { NEARBY_LOGS(INFO) << __func__ << "Ble v2 started advertising for legacy device."; - restarted_mediums.push_back(Medium::BLUETOOTH); + restarted_mediums.push_back(BLUETOOTH); NEARBY_LOGS(INFO) << __func__ << "After Ble v2 started advertising, for " "legacy, BT added to restarted mediums"; @@ -1578,18 +1727,40 @@ P2pClusterPcpHandler::UpdateAdvertisingOptionsImpl( } } else { - restarted_mediums.push_back(Medium::BLUETOOTH); + restarted_mediums.push_back(BLUETOOTH); } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error() + .operation_result_code() + .value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error() + .operation_result_code() + .value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); return StartOperationResult{.status = {Status::kBluetoothError}, - .mediums = restarted_mediums}; + .mediums = restarted_mediums, + .operation_result_with_mediums = std::move( + operation_result_with_mediums)}; } } } - return StartOperationResult{ - .status = status, - .mediums = restarted_mediums, - }; + return StartOperationResult{.status = status, + .mediums = restarted_mediums, + .operation_result_with_mediums = + std::move(operation_result_with_mediums)}; } BasePcpHandler::StartOperationResult @@ -1600,84 +1771,119 @@ P2pClusterPcpHandler::UpdateDiscoveryOptionsImpl( DiscoveryOptions old_options = client->GetDiscoveryOptions(); bool needs_restart = old_options.low_power != discovery_options.low_power; // ble - if (NeedsToTurnOffDiscoveryMedium(Medium::BLE, old_options, - discovery_options)) { + if (NeedsToTurnOffDiscoveryMedium(BLE, old_options, discovery_options)) { if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature::kEnableBleV2)) { ble_v2_medium_.StopScanning(std::string(service_id)); } else { ble_medium_.StopScanning(std::string(service_id)); } - StartEndpointLostByMediumAlarms(client, Medium::BLE); + StartEndpointLostByMediumAlarms(client, BLE); } // bt classic - if (NeedsToTurnOffDiscoveryMedium(Medium::BLUETOOTH, old_options, + if (NeedsToTurnOffDiscoveryMedium(BLUETOOTH, old_options, discovery_options) || needs_restart) { bluetooth_medium_.StopDiscovery(std::string(service_id)); - StartEndpointLostByMediumAlarms(client, Medium::BLUETOOTH); + StartEndpointLostByMediumAlarms(client, BLUETOOTH); } // wifi lan - if (NeedsToTurnOffDiscoveryMedium(Medium::WIFI_LAN, old_options, - discovery_options) || + if (NeedsToTurnOffDiscoveryMedium(WIFI_LAN, old_options, discovery_options) || needs_restart) { mediums_->GetWifiLan().StopDiscovery(std::string(service_id)); - StartEndpointLostByMediumAlarms(client, Medium::WIFI_LAN); + StartEndpointLostByMediumAlarms(client, WIFI_LAN); } // restart std::vector restarted_mediums; bool should_start_discovery = false; auto new_mediums = discovery_options.allowed; auto old_mediums = old_options.allowed; + std::vector + operation_result_with_mediums; + int update_index = + client->GetAnalyticsRecorder().GetNextDiscoveryUpdateIndex(); // ble if (new_mediums.ble) { should_start_discovery = true; if (old_mediums.ble) { - restarted_mediums.push_back(Medium::BLE); + restarted_mediums.push_back(BLE); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLE, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { + ErrorOr ble_result = {Error(OperationResultCode::DETAIL_UNKNOWN)}; if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: kEnableBleV2)) { - if (StartBleV2Scanning(client, std::string(service_id), - discovery_options) != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::BLE); + ble_result = StartBleV2Scanning(client, std::string(service_id), + discovery_options); + if (ble_result.has_value()) { + restarted_mediums.push_back(BLE); } else { NEARBY_LOGS(WARNING) << "UpdateDiscoveryOptionsImpl: unable to " "restart blev2 scanning"; } } else { - if (StartBleScanning( - client, std::string(service_id), - discovery_options.fast_advertisement_service_uuid) != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::BLE); + ble_result = + StartBleScanning(client, std::string(service_id), + discovery_options.fast_advertisement_service_uuid); + if (ble_result.has_value()) { + restarted_mediums.push_back(BLE); } else { NEARBY_LOGS(WARNING) << "UpdateDiscoveryOptionsImpl: unable to restart ble scanning"; } } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLE, update_index, + ble_result.has_error() + ? ble_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } // bt classic if (new_mediums.bluetooth && !discovery_options.low_power) { should_start_discovery = true; if (!needs_restart && old_mediums.bluetooth) { - restarted_mediums.push_back(Medium::BLUETOOTH); + restarted_mediums.push_back(BLUETOOTH); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { if (NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: kDisableBluetoothClassicScanning)) { - StartBluetoothDiscoveryWithPause(client, std::string(service_id), - discovery_options, restarted_mediums); + StartBluetoothDiscoveryWithPause( + client, std::string(service_id), discovery_options, + restarted_mediums, operation_result_with_mediums, update_index); } else { - if (StartBluetoothDiscovery(client, std::string(service_id)) != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::BLUETOOTH); + ErrorOr bluetooth_result = + StartBluetoothDiscovery(client, std::string(service_id)); + if (bluetooth_result.has_value()) { + restarted_mediums.push_back(BLUETOOTH); } else { NEARBY_LOGS(WARNING) << "UpdateDiscoveryOptionsImpl: unable to restart bt scanning"; } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error() + .operation_result_code() + .value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } } @@ -1685,24 +1891,43 @@ P2pClusterPcpHandler::UpdateDiscoveryOptionsImpl( if (new_mediums.wifi_lan && !discovery_options.low_power) { should_start_discovery = true; if (!needs_restart && old_mediums.wifi_lan) { - restarted_mediums.push_back(Medium::WIFI_LAN); + restarted_mediums.push_back(WIFI_LAN); + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, update_index, + OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { - if (StartWifiLanDiscovery(client, std::string(service_id)) != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { - restarted_mediums.push_back(Medium::WIFI_LAN); + ErrorOr wifi_lan_result = + StartWifiLanDiscovery(client, std::string(service_id)); + if (wifi_lan_result.has_value()) { + restarted_mediums.push_back(WIFI_LAN); } else { NEARBY_LOGS(WARNING) << "UpdateDiscoveryOptionsImpl: unable to restart " "wifi lan scanning"; } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, WIFI_LAN, update_index, + wifi_lan_result.has_error() + ? wifi_lan_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } if (restarted_mediums.empty() && should_start_discovery) { // All radios failed to start. return StartOperationResult{.status = {Status::kError}, - .mediums = restarted_mediums}; + .mediums = restarted_mediums, + .operation_result_with_mediums = + std::move(operation_result_with_mediums)}; } return StartOperationResult{.status = {Status::kSuccess}, - .mediums = restarted_mediums}; + .mediums = restarted_mediums, + .operation_result_with_mediums = + std::move(operation_result_with_mediums)}; } void P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler( @@ -1726,11 +1951,11 @@ void P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler( ByteArray remote_device_info{remote_device_name}; OnIncomingConnection(client, remote_device_info, std::move(channel), - Medium::BLUETOOTH, device_type); + BLUETOOTH, device_type); }); } -Medium P2pClusterPcpHandler::StartBluetoothAdvertising( +ErrorOr P2pClusterPcpHandler::StartBluetoothAdvertising( ClientProxy* client, const std::string& service_id, const ByteArray& service_id_hash, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, WebRtcState web_rtc_state) { @@ -1740,13 +1965,21 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << "P2pClusterPcpHandler::StartBluetoothAdvertising: service=" << service_id << ": start"; if (!bluetooth_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !bluetooth_medium_.StartAcceptingConnections( - service_id, - absl::bind_front( - &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, this, - client, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + ErrorOr error = true; + if (!bluetooth_radio_.Enable()) { + error = {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } else { + ErrorOr accept_result = bluetooth_medium_.StartAcceptingConnections( + service_id, + absl::bind_front( + &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, this, + client, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (accept_result.has_error()) { + error = {Error(accept_result.error().operation_result_code().value())}; + } + } + if (error.has_error()) { NEARBY_LOGS(WARNING) << "In StartBluetoothAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -1754,7 +1987,7 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << " failed to start listening for incoming Bluetooth " "connections to service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(error.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartBluetoothAdvertising(" @@ -1785,7 +2018,8 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << absl::BytesToHexString(local_endpoint_info.data()) << "}."; bluetooth_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error( + OperationResultCode::NEARBY_BLUETOOTH_ADVERTISE_TO_BYTES_FAILURE)}; } NEARBY_LOGS(INFO) << "In StartBluetoothAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -1794,7 +2028,9 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << " with service_id=" << service_id; // Become Bluetooth discoverable. - if (!bluetooth_medium_.TurnOnDiscoverability(device_name)) { + ErrorOr bluetooth_result = + bluetooth_medium_.TurnOnDiscoverability(device_name); + if (bluetooth_result.has_error()) { NEARBY_LOGS(INFO) << "In StartBluetoothAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -1802,7 +2038,7 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << " couldn't start Bluetooth advertising with BluetoothDeviceName " << device_name; bluetooth_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(bluetooth_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartBluetoothAdvertising(" @@ -1810,60 +2046,80 @@ Medium P2pClusterPcpHandler::StartBluetoothAdvertising( << "), client=" << client->GetClientId() << " started Bluetooth advertising with BluetoothDeviceName " << device_name; - return location::nearby::proto::connections::BLUETOOTH; + return {BLUETOOTH}; } -Medium P2pClusterPcpHandler::StartBluetoothDiscovery( +ErrorOr P2pClusterPcpHandler::StartBluetoothDiscovery( ClientProxy* client, const std::string& service_id) { - if (bluetooth_radio_.Enable() && - bluetooth_medium_.StartDiscovery( - service_id, - { - .device_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler, this, - client, service_id), - .device_name_changed_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothNameChangedHandler, this, - client, service_id), - .device_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothDeviceLostHandler, this, - client, service_id), - })) { + if (!bluetooth_radio_.Enable()) { NEARBY_LOGS(INFO) << "In StartBluetoothDiscovery(), client=" << client->GetClientId() - << " started scanning for Bluetooth for service_id=" + << " couldn't start scanning on Bluetooth for service_id=" << service_id; - return location::nearby::proto::connections::BLUETOOTH; - } else { + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + + ErrorOr result = bluetooth_medium_.StartDiscovery( + service_id, + { + .device_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler, this, + client, service_id), + .device_name_changed_cb = absl::bind_front( + &P2pClusterPcpHandler::BluetoothNameChangedHandler, this, client, + service_id), + .device_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BluetoothDeviceLostHandler, this, client, + service_id), + }); + if (result.has_error()) { NEARBY_LOGS(INFO) << "In StartBluetoothDiscovery(), client=" << client->GetClientId() << " couldn't start scanning on Bluetooth for service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(result.error().operation_result_code().value())}; } + + NEARBY_LOGS(INFO) << "In StartBluetoothDiscovery(), client=" + << client->GetClientId() + << " started scanning for Bluetooth for service_id=" + << service_id; + return {BLUETOOTH}; } void P2pClusterPcpHandler::StartBluetoothDiscoveryWithPause( ClientProxy* client, const std::string& service_id, const DiscoveryOptions& discovery_options, - std::vector& mediums_started_successfully) { + std::vector& mediums_started_successfully, + std::vector& + operation_result_with_mediums, + int update_index) { if (bluetooth_radio_.IsEnabled()) { if (ble_v2_medium_.IsExtendedAdvertisementsAvailable() && std::find(mediums_started_successfully.begin(), mediums_started_successfully.end(), - location::nearby::proto::connections::BLE) != - mediums_started_successfully.end()) { + BLE) != mediums_started_successfully.end()) { if (bluetooth_medium_.IsDiscovering(service_id)) { // If we are already discovering, we don't need to start again. - Medium bluetooth_medium = StartBluetoothDiscovery(client, service_id); - if (bluetooth_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ErrorOr bluetooth_result = + StartBluetoothDiscovery(client, service_id); + if (bluetooth_result.has_value()) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::" "StartBluetoothDiscoveryWithPause: BT added"; - mediums_started_successfully.push_back(bluetooth_medium); + mediums_started_successfully.push_back(*bluetooth_result); bluetooth_classic_client_id_to_service_id_map_.insert( {client->GetClientId(), service_id}); } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error() + .operation_result_code() + .value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } else { NEARBY_LOGS(INFO) << "Pause bluetooth discovery for service id : " << service_id; @@ -1872,15 +2128,23 @@ void P2pClusterPcpHandler::StartBluetoothDiscoveryWithPause( } else { // Always start bluetooth discovery if BLE doesn't support extended // advertisements. - Medium bluetooth_medium = StartBluetoothDiscovery(client, service_id); - if (bluetooth_medium != - location::nearby::proto::connections::UNKNOWN_MEDIUM) { + ErrorOr bluetooth_result = + StartBluetoothDiscovery(client, service_id); + if (bluetooth_result.has_value()) { NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::" "StartBluetoothDiscoveryWithPause: BT added"; - mediums_started_successfully.push_back(bluetooth_medium); + mediums_started_successfully.push_back(*bluetooth_result); bluetooth_classic_client_id_to_service_id_map_.insert( {client->GetClientId(), service_id}); } + std::unique_ptr + operation_result_with_medium = + GetOperationResultWithMediumByResultCode( + client, BLUETOOTH, update_index, + bluetooth_result.has_error() + ? bluetooth_result.error().operation_result_code().value() + : OperationResultCode::DETAIL_SUCCESS); + operation_result_with_mediums.push_back(*operation_result_with_medium); } } else { NEARBY_LOGS(WARNING) << "Ignore to discover on bluetooth for service id: " @@ -1896,30 +2160,32 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BluetoothConnectImpl( << endpoint->endpoint_id << ") over Bluetooth Classic."; BluetoothDevice& device = endpoint->bluetooth_device; - BluetoothSocket bluetooth_socket = bluetooth_medium_.Connect( + ErrorOr bluetooth_socket_result = bluetooth_medium_.Connect( device, endpoint->service_id, client->GetCancellationFlag(endpoint->endpoint_id)); - if (!bluetooth_socket.IsValid()) { + if (bluetooth_socket_result.has_error()) { NEARBY_LOGS(ERROR) << "In BluetoothConnectImpl(), failed to connect to Bluetooth device " << device.GetName() << " for endpoint(id=" << endpoint->endpoint_id << ")."; return BasePcpHandler::ConnectImplResult{ .status = {Status::kBluetoothError}, - }; + .operation_result_code = + bluetooth_socket_result.error().operation_result_code().value()}; } auto channel = std::make_unique( endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, - bluetooth_socket); + bluetooth_socket_result.value()); NEARBY_VLOG(1) << "Client" << client->GetClientId() << " created Bluetooth endpoint channel to endpoint(id=" << endpoint->endpoint_id << ")."; client->SetBluetoothMacAddress(endpoint->endpoint_id, device.GetMacAddress()); return BasePcpHandler::ConnectImplResult{ - .medium = Medium::BLUETOOTH, + .medium = BLUETOOTH, .status = {Status::kSuccess}, - .endpoint_channel = std::move(channel), + .operation_result_code = OperationResultCode::DETAIL_SUCCESS, + .endpoint_channel = std::move(channel) }; } @@ -1946,11 +2212,11 @@ void P2pClusterPcpHandler::BleConnectionAcceptedHandler( socket.GetRemotePeripheral().GetAdvertisementBytes(service_id); OnIncomingConnection(client, remote_peripheral_info, - std::move(channel), Medium::BLE, device_type); + std::move(channel), BLE, device_type); }); } -Medium P2pClusterPcpHandler::StartBleAdvertising( +ErrorOr P2pClusterPcpHandler::StartBleAdvertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state) { @@ -1967,12 +2233,7 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartBleAdvertising: service_id=" << service_id << " : start"; if (!ble_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !ble_medium_.StartAcceptingConnections( - service_id, absl::bind_front( - &P2pClusterPcpHandler::BleConnectionAcceptedHandler, - this, client, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + if (!bluetooth_radio_.Enable()) { NEARBY_LOGS(WARNING) << "In StartBleAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -1980,7 +2241,22 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( << " failed to start accepting for incoming BLE connections to " "service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr accept_result = ble_medium_.StartAcceptingConnections( + service_id, + absl::bind_front(&P2pClusterPcpHandler::BleConnectionAcceptedHandler, + this, client, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (!accept_result.has_value()) { + NEARBY_LOGS(WARNING) + << "In StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to start accepting for incoming BLE connections to " + "service_id=" + << service_id; + return {Error(accept_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartBleAdvertising(" @@ -1994,13 +2270,24 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( ShouldAcceptBluetoothConnections(advertising_options)) { if (bluetooth_medium_.IsAvailable() && !bluetooth_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !bluetooth_medium_.StartAcceptingConnections( - service_id, - absl::bind_front( - &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, - this, client, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + if (!bluetooth_radio_.Enable()) { + NEARBY_LOGS(WARNING) + << "In BT StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to start accepting for incoming BLE connections to " + "service_id=" + << service_id; + return { + Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr accept_result = bluetooth_medium_.StartAcceptingConnections( + service_id, + absl::bind_front( + &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, this, + client, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (!accept_result.has_value()) { NEARBY_LOGS(WARNING) << "In BT StartBleAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2009,7 +2296,7 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( "service_id=" << service_id; ble_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(accept_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In BT StartBleAdvertising(" @@ -2053,7 +2340,7 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( << "), client=" << client->GetClientId() << " failed to create an advertisement."; ble_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(OperationResultCode::NEARBY_BLE_ADVERTISE_TO_BYTES_FAILURE)}; } NEARBY_LOGS(INFO) << "In StartBleAdvertising(" @@ -2063,9 +2350,10 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( << service_id << ", bytes: " << absl::BytesToHexString(advertisement_bytes.data()); - if (!ble_medium_.StartAdvertising( - service_id, advertisement_bytes, - advertising_options.fast_advertisement_service_uuid)) { + ErrorOr ble_result = ble_medium_.StartAdvertising( + service_id, advertisement_bytes, + advertising_options.fast_advertisement_service_uuid); + if (ble_result.has_error()) { NEARBY_LOGS(WARNING) << "In StartBleAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2073,7 +2361,7 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( << " couldn't start BLE Advertising with BleAdvertisement " << absl::BytesToHexString(advertisement_bytes.data()); ble_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(ble_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In startBleAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2081,34 +2369,40 @@ Medium P2pClusterPcpHandler::StartBleAdvertising( << "), client=" << client->GetClientId() << " started BLE Advertising with BleAdvertisement " << absl::BytesToHexString(advertisement_bytes.data()); - return location::nearby::proto::connections::BLE; + return {BLE}; } -Medium P2pClusterPcpHandler::StartBleScanning( +ErrorOr P2pClusterPcpHandler::StartBleScanning( ClientProxy* client, const std::string& service_id, const std::string& fast_advertisement_service_uuid) { - if (bluetooth_radio_.Enable() && - ble_medium_.StartScanning( - service_id, fast_advertisement_service_uuid, - { - .peripheral_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralDiscoveredHandler, this, - client), - .peripheral_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralLostHandler, this, - client), - })) { + if (!bluetooth_radio_.Enable()) { + NEARBY_LOGS(INFO) << "In StartBleScanning(), client=" + << client->GetClientId() + << " couldn't start scanning on BLE for service_id=" + << service_id; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr result = ble_medium_.StartScanning( + service_id, fast_advertisement_service_uuid, + { + .peripheral_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BlePeripheralDiscoveredHandler, this, + client), + .peripheral_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BlePeripheralLostHandler, this, client), + }); + if (!result.has_error()) { NEARBY_LOGS(INFO) << "In StartBleScanning(), client=" << client->GetClientId() << " started scanning for BLE advertisements for service_id=" << service_id; - return location::nearby::proto::connections::BLE; + return {BLE}; } else { NEARBY_LOGS(INFO) << "In StartBleScanning(), client=" << client->GetClientId() << " couldn't start scanning on BLE for service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(result.error().operation_result_code().value())}; } } @@ -2120,25 +2414,29 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleConnectImpl( BlePeripheral& peripheral = endpoint->ble_peripheral; - BleSocket ble_socket = + ErrorOr ble_socket_result = ble_medium_.Connect(peripheral, endpoint->service_id, client->GetCancellationFlag(endpoint->endpoint_id)); - if (!ble_socket.IsValid()) { + if (ble_socket_result.has_error()) { NEARBY_LOGS(ERROR) << "In BleConnectImpl(), failed to connect to BLE device " << peripheral.GetName() << " for endpoint(id=" << endpoint->endpoint_id << ")."; return BasePcpHandler::ConnectImplResult{ .status = {Status::kBleError}, + .operation_result_code = + ble_socket_result.error().operation_result_code().value(), }; } auto channel = std::make_unique( - endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, ble_socket); + endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, + ble_socket_result.value()); return BasePcpHandler::ConnectImplResult{ - .medium = Medium::BLE, + .medium = BLE, .status = {Status::kSuccess}, + .operation_result_code = OperationResultCode::DETAIL_SUCCESS, .endpoint_channel = std::move(channel), }; } @@ -2162,11 +2460,11 @@ void P2pClusterPcpHandler::BleV2ConnectionAcceptedHandler( service_id, std::string(remote_peripheral_info), socket); OnIncomingConnection(client, remote_peripheral_info, std::move(channel), - Medium::BLE, device_type); + BLE, device_type); }); } -Medium P2pClusterPcpHandler::StartBleV2Advertising( +ErrorOr P2pClusterPcpHandler::StartBleV2Advertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state) { @@ -2178,13 +2476,22 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( << "P2pClusterPcpHandler::StartBleV2Advertising: service_id=" << service_id << " : start"; if (!ble_v2_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !ble_v2_medium_.StartAcceptingConnections( - service_id, - absl::bind_front( - &P2pClusterPcpHandler::BleV2ConnectionAcceptedHandler, this, - client, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + if (!bluetooth_radio_.Enable()) { + NEARBY_LOGS(WARNING) + << "In StartBleV2Advertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to start accepting for incoming BLE connections to " + "service_id=" + << service_id; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr ble_v2_result = ble_v2_medium_.StartAcceptingConnections( + service_id, + absl::bind_front(&P2pClusterPcpHandler::BleV2ConnectionAcceptedHandler, + this, client, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (ble_v2_result.has_error()) { NEARBY_LOGS(WARNING) << "In StartBleV2Advertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2192,7 +2499,7 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( << " failed to start accepting for incoming BLE connections to " "service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(ble_v2_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartBleV2Advertising(" @@ -2209,13 +2516,24 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( ShouldAcceptBluetoothConnections(advertising_options)) { if (bluetooth_medium_.IsAvailable() && !bluetooth_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !bluetooth_medium_.StartAcceptingConnections( - service_id, - absl::bind_front( - &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, - this, client, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + if (!bluetooth_radio_.Enable()) { + NEARBY_LOGS(WARNING) + << "In BT StartBleV2Advertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to start accepting for incoming BLE connections to " + "service_id=" + << service_id; + return { + Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr accept_result = bluetooth_medium_.StartAcceptingConnections( + service_id, + absl::bind_front( + &P2pClusterPcpHandler::BluetoothConnectionAcceptedHandler, this, + client, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (accept_result.has_error()) { NEARBY_LOGS(WARNING) << "In BT StartBleV2Advertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2224,7 +2542,7 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( "service_id=" << service_id; ble_v2_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(accept_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In BT StartBleV2Advertising(" @@ -2269,7 +2587,7 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( << "), client=" << client->GetClientId() << " failed to create an advertisement."; ble_v2_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(OperationResultCode::NEARBY_BLE_ADVERTISE_TO_BYTES_FAILURE)}; } NEARBY_LOGS(INFO) << "In StartBleV2Advertising(" @@ -2278,9 +2596,10 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( << " generated BleAdvertisement with service_id=" << service_id; - if (!ble_v2_medium_.StartAdvertising( - service_id, advertisement_bytes, power_level, - !advertising_options.fast_advertisement_service_uuid.empty())) { + ErrorOr ble_v2_result = ble_v2_medium_.StartAdvertising( + service_id, advertisement_bytes, power_level, + !advertising_options.fast_advertisement_service_uuid.empty()); + if (ble_v2_result.has_error()) { NEARBY_LOGS(WARNING) << "In StartBleV2Advertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2288,49 +2607,54 @@ Medium P2pClusterPcpHandler::StartBleV2Advertising( << " couldn't start BLE Advertising with BleAdvertisement " << absl::BytesToHexString(advertisement_bytes.data()); ble_v2_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(ble_v2_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartBleV2Advertising(" << absl::BytesToHexString(local_endpoint_info.data()) << "), client=" << client->GetClientId() << " started BLE Advertising with BleAdvertisement " << absl::BytesToHexString(advertisement_bytes.data()); - return location::nearby::proto::connections::BLE; + return {BLE}; } -Medium P2pClusterPcpHandler::StartBleV2Scanning( +ErrorOr P2pClusterPcpHandler::StartBleV2Scanning( ClientProxy* client, const std::string& service_id, const DiscoveryOptions& discovery_options) { PowerLevel power_level = discovery_options.low_power ? PowerLevel::kLowPower : PowerLevel::kHighPower; - if (bluetooth_radio_.Enable() && - ble_v2_medium_.StartScanning( - service_id, power_level, - { - .peripheral_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler, this, - client), - .peripheral_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BleV2PeripheralLostHandler, this, - client), - .instant_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BleV2InstantLostHandler, this, client), - .legacy_device_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BleV2LegacyDeviceDiscoveredHandler, - this), - })) { + if (!bluetooth_radio_.Enable()) { + NEARBY_LOGS(INFO) << "In StartBleV2Scanning(), client=" + << client->GetClientId() + << " couldn't start scanning on BLE for service_id=" + << service_id; + return {Error(OperationResultCode::DEVICE_STATE_RADIO_ENABLING_FAILURE)}; + } + ErrorOr ble_v2_result = ble_v2_medium_.StartScanning( + service_id, power_level, + { + .peripheral_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler, this, + client), + .peripheral_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2PeripheralLostHandler, this, client), + .instant_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2InstantLostHandler, this, client), + .legacy_device_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2LegacyDeviceDiscoveredHandler, this), + }); + if (!ble_v2_result.has_error()) { NEARBY_LOGS(INFO) << "In StartBleV2Scanning(), client=" << client->GetClientId() << " started scanning for BLE advertisements for service_id=" << service_id; - return location::nearby::proto::connections::BLE; + return {BLE}; } NEARBY_LOGS(INFO) << "In StartBleV2Scanning(), client=" << client->GetClientId() << " couldn't start scanning on BLE for service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(ble_v2_result.error().operation_result_code().value())}; } BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleV2ConnectImpl( @@ -2341,25 +2665,29 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleV2ConnectImpl( BleV2Peripheral& peripheral = endpoint->ble_peripheral; - BleV2Socket ble_socket = ble_v2_medium_.Connect( + ErrorOr ble_socket_result = ble_v2_medium_.Connect( endpoint->service_id, peripheral, client->GetCancellationFlag(endpoint->endpoint_id)); - if (!ble_socket.IsValid()) { + if (ble_socket_result.has_error()) { NEARBY_LOGS(ERROR) << "In BleV2ConnectImpl(), failed to connect to BLE device " << absl::BytesToHexString(peripheral.GetId().data()) << " for endpoint(id=" << endpoint->endpoint_id << ")."; return BasePcpHandler::ConnectImplResult{ .status = {Status::kBleError}, + .operation_result_code = + ble_socket_result.error().operation_result_code().value(), }; } auto channel = std::make_unique( - endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, ble_socket); + endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, + ble_socket_result.value()); return BasePcpHandler::ConnectImplResult{ - .medium = Medium::BLE, + .medium = BLE, .status = {Status::kSuccess}, + .operation_result_code = OperationResultCode::DETAIL_SUCCESS, .endpoint_channel = std::move(channel), }; } @@ -2384,11 +2712,11 @@ void P2pClusterPcpHandler::WifiLanConnectionAcceptedHandler( ByteArray remote_service_name_byte{remote_service_name}; OnIncomingConnection(client, remote_service_name_byte, - std::move(channel), Medium::WIFI_LAN, device_type); + std::move(channel), WIFI_LAN, device_type); }); } -Medium P2pClusterPcpHandler::StartWifiLanAdvertising( +ErrorOr P2pClusterPcpHandler::StartWifiLanAdvertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, WebRtcState web_rtc_state) { @@ -2397,12 +2725,13 @@ Medium P2pClusterPcpHandler::StartWifiLanAdvertising( NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartWifiLanAdvertising: service=" << service_id << ": start"; if (!wifi_lan_medium_.IsAcceptingConnections(service_id)) { - if (!wifi_lan_medium_.StartAcceptingConnections( - service_id, - absl::bind_front( - &P2pClusterPcpHandler::WifiLanConnectionAcceptedHandler, this, - client, local_endpoint_id, local_endpoint_info.AsStringView(), - NearbyDevice::Type::kConnectionsDevice))) { + ErrorOr wifi_lan_result = wifi_lan_medium_.StartAcceptingConnections( + service_id, + absl::bind_front( + &P2pClusterPcpHandler::WifiLanConnectionAcceptedHandler, this, + client, local_endpoint_id, local_endpoint_info.AsStringView(), + NearbyDevice::Type::kConnectionsDevice)); + if (wifi_lan_result.has_error()) { NEARBY_LOGS(WARNING) << "In StartWifiLanAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2410,7 +2739,7 @@ Medium P2pClusterPcpHandler::StartWifiLanAdvertising( << " failed to start listening for incoming WifiLan connections " "to service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(wifi_lan_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2446,7 +2775,8 @@ Medium P2pClusterPcpHandler::StartWifiLanAdvertising( << absl::BytesToHexString(local_endpoint_info.data()) << "}."; wifi_lan_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return { + Error(OperationResultCode::NEARBY_WIFI_LAN_ADVERTISE_TO_BYTES_FAILURE)}; } NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) @@ -2455,46 +2785,48 @@ Medium P2pClusterPcpHandler::StartWifiLanAdvertising( << nsd_service_info.GetServiceName() << " with service_id=" << service_id; - if (!wifi_lan_medium_.StartAdvertising(service_id, nsd_service_info)) { + ErrorOr wifi_lan_result = + wifi_lan_medium_.StartAdvertising(service_id, nsd_service_info); + if (wifi_lan_result.has_error()) { NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) << "), client=" << client->GetClientId() << " couldn't advertise with WifiLanServiceInfo " << nsd_service_info.GetServiceName(); wifi_lan_medium_.StopAcceptingConnections(service_id); - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(wifi_lan_result.error().operation_result_code().value())}; } NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) << "), client=" << client->GetClientId() << " advertised with WifiLanServiceInfo " << nsd_service_info.GetServiceName(); - return location::nearby::proto::connections::WIFI_LAN; + return {WIFI_LAN}; } -Medium P2pClusterPcpHandler::StartWifiLanDiscovery( +ErrorOr P2pClusterPcpHandler::StartWifiLanDiscovery( ClientProxy* client, const std::string& service_id) { - if (wifi_lan_medium_.StartDiscovery( - service_id, - { - .service_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler, this, - client), - .service_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::WifiLanServiceLostHandler, this, - client), - })) { + ErrorOr result = wifi_lan_medium_.StartDiscovery( + service_id, + { + .service_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler, this, + client), + .service_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::WifiLanServiceLostHandler, this, client), + }); + if (!result.has_error()) { NEARBY_LOGS(INFO) << "In StartWifiLanDiscovery(), client=" << client->GetClientId() << " started scanning for Wifi devices for service_id=" << service_id; - return location::nearby::proto::connections::WIFI_LAN; + return {WIFI_LAN}; } else { NEARBY_LOGS(INFO) << "In StartWifiLanDiscovery(), client=" << client->GetClientId() << " couldn't start scanning on Wifi for service_id=" << service_id; - return location::nearby::proto::connections::UNKNOWN_MEDIUM; + return {Error(result.error().operation_result_code().value())}; } } @@ -2503,30 +2835,34 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl( NEARBY_LOGS(INFO) << "Client " << client->GetClientId() << " is attempting to connect to endpoint(id=" << endpoint->endpoint_id << ") over WifiLan."; - WifiLanSocket socket = wifi_lan_medium_.Connect( + ErrorOr socket_result = wifi_lan_medium_.Connect( endpoint->service_id, endpoint->service_info, client->GetCancellationFlag(endpoint->endpoint_id)); - if (!socket.IsValid()) { + if (socket_result.has_error()) { NEARBY_LOGS(ERROR) << "In WifiLanConnectImpl(), failed to connect to service " << endpoint->service_info.GetServiceName() << " for endpoint(id=" << endpoint->endpoint_id << ")."; return BasePcpHandler::ConnectImplResult{ - .status = {Status::kWifiLanError}, + .status = {Status::kWifiLanError}, + .operation_result_code = + socket_result.error().operation_result_code().value(), }; } NEARBY_LOGS(INFO) << "In WifiLanConnectImpl(), connect to service " - << " socket=" << &socket.GetImpl() + << " socket=" << &socket_result.value().GetImpl() << " for endpoint(id=" << endpoint->endpoint_id << ")."; auto channel = std::make_unique( - endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, socket); + endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, + socket_result.value()); NEARBY_LOGS(INFO) << "Client " << client->GetClientId() << " created WifiLan endpoint channel to endpoint(id=" << endpoint->endpoint_id << ")."; return BasePcpHandler::ConnectImplResult{ - .medium = Medium::WIFI_LAN, + .medium = WIFI_LAN, .status = {Status::kSuccess}, + .operation_result_code = OperationResultCode::DETAIL_SUCCESS, .endpoint_channel = std::move(channel), }; } diff --git a/connections/implementation/p2p_cluster_pcp_handler.h b/connections/implementation/p2p_cluster_pcp_handler.h index 606b781683..bcdd661e51 100644 --- a/connections/implementation/p2p_cluster_pcp_handler.h +++ b/connections/implementation/p2p_cluster_pcp_handler.h @@ -61,6 +61,7 @@ #include "connections/implementation/pcp.h" #include "connections/implementation/wifi_lan_service_info.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -196,16 +197,21 @@ class P2pClusterPcpHandler : public BasePcpHandler { NearbyDevice::Type device_type, const std::string& service_id, BluetoothSocket socket); - location::nearby::proto::connections::Medium StartBluetoothAdvertising( - ClientProxy* client, const std::string& service_id, - const ByteArray& service_id_hash, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, WebRtcState web_rtc_state); - location::nearby::proto::connections::Medium StartBluetoothDiscovery( + ErrorOr + StartBluetoothAdvertising(ClientProxy* client, const std::string& service_id, + const ByteArray& service_id_hash, + const std::string& local_endpoint_id, + const ByteArray& local_endpoint_info, + WebRtcState web_rtc_state); + ErrorOr StartBluetoothDiscovery( ClientProxy* client, const std::string& service_id); void StartBluetoothDiscoveryWithPause( ClientProxy* client, const std::string& service_id, const DiscoveryOptions& discovery_options, - std::vector& mediums_started_successfully); + std::vector& mediums_started_successfully, + std::vector& operation_result_with_mediums, + int update_index); BasePcpHandler::ConnectImplResult BluetoothConnectImpl( ClientProxy* client, BluetoothEndpoint* endpoint); @@ -224,12 +230,12 @@ class P2pClusterPcpHandler : public BasePcpHandler { NearbyDevice::Type device_type, BleSocket socket, const std::string& service_id); - location::nearby::proto::connections::Medium StartBleAdvertising( + ErrorOr StartBleAdvertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state); - location::nearby::proto::connections::Medium StartBleScanning( + ErrorOr StartBleScanning( ClientProxy* client, const std::string& service_id, const std::string& fast_advertisement_service_uuid); BasePcpHandler::ConnectImplResult BleConnectImpl(ClientProxy* client, @@ -259,12 +265,12 @@ class P2pClusterPcpHandler : public BasePcpHandler { NearbyDevice::Type device_type, BleV2Socket socket, const std::string& service_id); - location::nearby::proto::connections::Medium StartBleV2Advertising( + ErrorOr StartBleV2Advertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state); - location::nearby::proto::connections::Medium StartBleV2Scanning( + ErrorOr StartBleV2Scanning( ClientProxy* client, const std::string& service_id, const DiscoveryOptions& discovery_options); BasePcpHandler::ConnectImplResult BleV2ConnectImpl(ClientProxy* client, @@ -286,11 +292,11 @@ class P2pClusterPcpHandler : public BasePcpHandler { NearbyDevice::Type device_type, const std::string& service_id, WifiLanSocket socket); - location::nearby::proto::connections::Medium StartWifiLanAdvertising( + ErrorOr StartWifiLanAdvertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, WebRtcState web_rtc_state); - location::nearby::proto::connections::Medium StartWifiLanDiscovery( + ErrorOr StartWifiLanDiscovery( ClientProxy* client, const std::string& service_id); BasePcpHandler::ConnectImplResult WifiLanConnectImpl( ClientProxy* client, WifiLanEndpoint* endpoint); diff --git a/connections/implementation/payload_manager.cc b/connections/implementation/payload_manager.cc index 12d333e0e5..81abd3124b 100644 --- a/connections/implementation/payload_manager.cc +++ b/connections/implementation/payload_manager.cc @@ -23,26 +23,32 @@ #include #include +#include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/functional/bind_front.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/time/clock.h" #include "absl/time/time.h" +#include "connections/implementation/analytics/packet_meta_data.h" #include "connections/implementation/analytics/throughput_recorder.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" #include "connections/implementation/flags/nearby_connections_feature_flags.h" +#include "connections/implementation/internal_payload.h" #include "connections/implementation/internal_payload_factory.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "connections/listeners.h" +#include "connections/medium_selector.h" #include "connections/payload.h" #include "connections/payload_type.h" +#include "connections/status.h" #include "internal/flags/nearby_flags.h" #include "internal/platform/byte_array.h" #include "internal/platform/count_down_latch.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/logging.h" #include "internal/platform/mutex_lock.h" @@ -52,20 +58,19 @@ namespace nearby { namespace connections { +namespace { using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::connections::PayloadTransferFrame; using ::location::nearby::connections::V1Frame; +using ::location::nearby::proto::connections::Medium; +using ::location::nearby::proto::connections::OperationResultCode; using ::location::nearby::proto::connections::PayloadStatus; -using ::nearby::analytics::PacketMetaData; +using PacketMetaData = ::nearby::analytics::PacketMetaData; using ::nearby::analytics::ThroughputRecorderContainer; -using ::nearby::connections::PayloadDirection; +using PayloadDirection = ::nearby::connections::PayloadDirection; -namespace { constexpr absl::Duration kMinTransferUpdateInterval = absl::Milliseconds(50); -} - -// C++14 requires to declare this. -// TODO(apolyudov): remove when migration to c++17 is possible. -constexpr absl::Duration PayloadManager::kWaitCloseTimeout; +} // namespace bool PayloadManager::SendPayloadLoop( ClientProxy* client, PendingPayload& pending_payload, @@ -82,6 +87,7 @@ bool PayloadManager::SendPayloadLoop( for (const auto& endpoint : unavailable_endpoints) { HandleFinishedOutgoingPayload( client, {endpoint->id}, payload_header, next_chunk_offset, + EndpointInfoStatusToOperationResultCode(endpoint->status.Get()), EndpointInfoStatusToPayloadStatus(endpoint->status.Get())); } @@ -100,10 +106,10 @@ bool PayloadManager::SendPayloadLoop( LOG(INFO) << "Aborting send of payload_id=" << pending_payload.GetInternalPayload()->GetId() << " at offset " << next_chunk_offset << " since it is marked canceled."; - HandleFinishedOutgoingPayload(client, available_endpoint_ids, - payload_header, next_chunk_offset, - location::nearby::proto::connections:: - PayloadStatus::LOCAL_CANCELLATION); + HandleFinishedOutgoingPayload( + client, available_endpoint_ids, payload_header, next_chunk_offset, + OperationResultCode::CLIENT_CANCELLATION_LOCAL_CANCEL_PAYLOAD, + PayloadStatus::LOCAL_CANCELLATION); return false; } @@ -119,9 +125,10 @@ bool PayloadManager::SendPayloadLoop( LOG(WARNING) << "PayloadManager failed to skip offset " << resume_offset << " on payload_id " << pending_payload.GetInternalPayload()->GetId(); - HandleFinishedOutgoingPayload( - client, available_endpoint_ids, payload_header, next_chunk_offset, - location::nearby::proto::connections::PayloadStatus::LOCAL_ERROR); + HandleFinishedOutgoingPayload(client, available_endpoint_ids, + payload_header, next_chunk_offset, + OperationResultCode::IO_FILE_READING_ERROR, + PayloadStatus::LOCAL_ERROR); return false; } NEARBY_VLOG(1) << "PayloadManager successfully skipped " @@ -151,7 +158,7 @@ bool PayloadManager::SendPayloadLoop( << pending_payload.GetInternalPayload()->GetId(); HandleFinishedOutgoingPayload( client, available_endpoint_ids, payload_header, next_chunk_offset, - location::nearby::proto::connections::PayloadStatus::LOCAL_ERROR); + OperationResultCode::IO_FILE_READING_ERROR, PayloadStatus::LOCAL_ERROR); return false; } @@ -168,10 +175,10 @@ bool PayloadManager::SendPayloadLoop( LOG(INFO) << "Payload xfer: endpoints failed: payload_id=" << payload_header.id() << "; endpoint_ids={" << ToString(failed_endpoint_ids) << "}", - HandleFinishedOutgoingPayload(client, failed_endpoint_ids, - payload_header, next_chunk_offset, - location::nearby::proto::connections:: - PayloadStatus::ENDPOINT_IO_ERROR); + HandleFinishedOutgoingPayload( + client, failed_endpoint_ids, payload_header, next_chunk_offset, + OperationResultCode::CONNECTIVITY_GENERIC_WRITING_CHANNEL_IO_ERROR, + PayloadStatus::ENDPOINT_IO_ERROR); } bool is_last_chunk = IsLastChunk(payload_chunk); // Check whether at least one endpoint succeeded -- if they all failed, @@ -298,7 +305,14 @@ std::string PayloadManager::ToString(EndpointInfo::Status status) { // Creates and starts tracking a PendingPayload for this Payload. Payload::Id PayloadManager::CreateOutgoingPayload( Payload payload, const EndpointIds& endpoint_ids) { - auto internal_payload{CreateOutgoingInternalPayload(std::move(payload))}; + ErrorOr> result = + CreateOutgoingInternalPayload(std::move(payload)); + if (result.has_error()) { + LOG(ERROR) << "Failed to create outgoing internal payload: " + << result.error().operation_result_code().value(); + return Payload::Id(); + } + std::unique_ptr internal_payload = std::move(result.value()); Payload::Id payload_id = internal_payload->GetId(); LOG(INFO) << "CreateOutgoingPayload: payload_id=" << payload_id; MutexLock lock(&mutex_); @@ -413,9 +427,10 @@ void PayloadManager::SendPayload(ClientProxy* client, // with. This should never be reached since the ServiceControllerRouter has // already checked whether or not we can work with this Payload type. if (!executor) { - RecordInvalidPayloadAnalytics(client, endpoint_ids, payload.GetId(), - payload.GetType(), payload.GetOffset(), - payload_total_size); + RecordInvalidPayloadAnalytics( + client, endpoint_ids, payload.GetId(), payload.GetType(), + payload.GetOffset(), payload_total_size, + OperationResultCode::NEARBY_GENERIC_OUTGOING_PAYLOAD_CREATION_FAILURE); LOG(INFO) << "PayloadManager failed to determine the right executor for " "outgoing payload_id=" << payload.GetId() @@ -441,9 +456,11 @@ void PayloadManager::SendPayload(ClientProxy* client, if (shutdown_.Get()) return; PendingPayloadHandle pending_payload = GetPayload(payload_id); if (!pending_payload) { - RecordInvalidPayloadAnalytics(client, endpoint_ids, payload_id, - payload_type, resume_offset, - payload_total_size); + RecordInvalidPayloadAnalytics( + client, endpoint_ids, payload_id, payload_type, resume_offset, + payload_total_size, + OperationResultCode:: + NEARBY_GENERIC_OUTGOING_PAYLOAD_CREATION_FAILURE); LOG(INFO) << "PayloadManager failed to create InternalPayload for outgoing " "payload_id=" @@ -513,11 +530,11 @@ Status PayloadManager::CancelPayload(ClientProxy* client, } // @EndpointManagerDataPool -void PayloadManager::OnIncomingFrame( - OfflineFrame& offline_frame, const std::string& from_endpoint_id, - ClientProxy* to_client, - location::nearby::proto::connections::Medium current_medium, - PacketMetaData& packet_meta_data) { +void PayloadManager::OnIncomingFrame(OfflineFrame& offline_frame, + const std::string& from_endpoint_id, + ClientProxy* to_client, + Medium current_medium, + PacketMetaData& packet_meta_data) { PayloadTransferFrame& frame = *offline_frame.mutable_v1()->mutable_payload_transfer(); @@ -607,25 +624,36 @@ void PayloadManager::OnEndpointDisconnect(ClientProxy* client, client->OnPayloadProgress(endpoint_id, update); PayloadStatus payload_status; + OperationResultCode operation_result_code; switch (reason) { case DisconnectionReason::LOCAL_DISCONNECTION: payload_status = PayloadStatus::LOCAL_CLIENT_DISCONNECTION; + operation_result_code = + OperationResultCode::CLIENT_CANCELLATION_LOCAL_DISCONNECT; break; case DisconnectionReason::REMOTE_DISCONNECTION: payload_status = PayloadStatus::REMOTE_CLIENT_DISCONNECTION; + operation_result_code = + OperationResultCode::CLIENT_CANCELLATION_REMOTE_DISCONNECT; break; case DisconnectionReason::IO_ERROR: default: payload_status = PayloadStatus::ENDPOINT_IO_ERROR; + operation_result_code = + client->GetAnalyticsRecorder() + .GetChannelIoErrorResultCodeFromMedium( + client->GetConnectedMedium(endpoint_id)); break; } if (pending_payload->IsIncoming()) { client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, pending_payload->GetId(), payload_status); + endpoint_id, pending_payload->GetId(), payload_status, + operation_result_code); } else { client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, pending_payload->GetId(), payload_status); + endpoint_id, pending_payload->GetId(), payload_status, + operation_result_code); } }); @@ -633,46 +661,69 @@ void PayloadManager::OnEndpointDisconnect(ClientProxy* client, }); } -location::nearby::proto::connections::PayloadStatus -PayloadManager::EndpointInfoStatusToPayloadStatus(EndpointInfo::Status status) { +PayloadStatus PayloadManager::EndpointInfoStatusToPayloadStatus( + EndpointInfo::Status status) { + switch (status) { + case EndpointInfo::Status::kCanceled: + return PayloadStatus::REMOTE_CANCELLATION; + case EndpointInfo::Status::kError: + return PayloadStatus::REMOTE_ERROR; + case EndpointInfo::Status::kAvailable: + return PayloadStatus::SUCCESS; + default: + LOG(INFO) << "PayloadManager: Unknown PayloadStatus"; + return PayloadStatus::UNKNOWN_PAYLOAD_STATUS; + } +} + +OperationResultCode PayloadManager::EndpointInfoStatusToOperationResultCode( + EndpointInfo::Status status) { switch (status) { case EndpointInfo::Status::kCanceled: - return location::nearby::proto::connections::PayloadStatus:: - REMOTE_CANCELLATION; + return OperationResultCode::CLIENT_CANCELLATION_REMOTE_IN_CANCELED_STATE; case EndpointInfo::Status::kError: - return location::nearby::proto::connections::PayloadStatus::REMOTE_ERROR; + return OperationResultCode::NEARBY_GENERIC_REMOTE_ENDPOINT_STATUS_ERROR; case EndpointInfo::Status::kAvailable: - return location::nearby::proto::connections::PayloadStatus::SUCCESS; + return OperationResultCode::DETAIL_SUCCESS; default: LOG(INFO) << "PayloadManager: Unknown PayloadStatus"; - return location::nearby::proto::connections::PayloadStatus:: - UNKNOWN_PAYLOAD_STATUS; + return OperationResultCode::DETAIL_UNKNOWN; } } -location::nearby::proto::connections::PayloadStatus -PayloadManager::ControlMessageEventToPayloadStatus( +PayloadStatus PayloadManager::ControlMessageEventToPayloadStatus( PayloadTransferFrame::ControlMessage::EventType event) { switch (event) { case PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR: - return location::nearby::proto::connections::PayloadStatus::REMOTE_ERROR; + return PayloadStatus::REMOTE_ERROR; case PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED: - return location::nearby::proto::connections::PayloadStatus:: - REMOTE_CANCELLATION; + return PayloadStatus::REMOTE_CANCELLATION; default: LOG(INFO) << "PayloadManager: unknown event=" << event; - return location::nearby::proto::connections::PayloadStatus:: - UNKNOWN_PAYLOAD_STATUS; + return PayloadStatus::UNKNOWN_PAYLOAD_STATUS; + } +} + +OperationResultCode PayloadManager::ControlMessageEventToOperationResultCode( + PayloadTransferFrame::ControlMessage::EventType event) { + switch (event) { + case PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR: + return OperationResultCode::NEARBY_GENERIC_REMOTE_REPORT_PAYLOADS_ERROR; + case PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED: + return OperationResultCode::CLIENT_CANCELLATION_REMOTE_CANCEL_PAYLOAD; + default: + LOG(INFO) << "PayloadManager: unknown event=" << event; + return OperationResultCode::DETAIL_UNKNOWN; } } PayloadProgressInfo::Status PayloadManager::PayloadStatusToTransferUpdateStatus( - location::nearby::proto::connections::PayloadStatus status) { + PayloadStatus status) { switch (status) { - case location::nearby::proto::connections::LOCAL_CANCELLATION: - case location::nearby::proto::connections::REMOTE_CANCELLATION: + case PayloadStatus::LOCAL_CANCELLATION: + case PayloadStatus::REMOTE_CANCELLATION: return PayloadProgressInfo::Status::kCanceled; - case location::nearby::proto::connections::SUCCESS: + case PayloadStatus::SUCCESS: return PayloadProgressInfo::Status::kSuccess; default: return PayloadProgressInfo::Status::kFailure; @@ -742,14 +793,15 @@ PayloadTransferFrame::PayloadChunk PayloadManager::CreatePayloadChunk( return payload_chunk; } -PayloadManager::PendingPayloadHandle PayloadManager::CreateIncomingPayload( - const PayloadTransferFrame& frame, const std::string& endpoint_id) { - auto internal_payload = +ErrorOr +PayloadManager::CreateIncomingPayload(const PayloadTransferFrame& frame, + const std::string& endpoint_id) { + ErrorOr> result = CreateIncomingInternalPayload(frame, custom_save_path_); - if (!internal_payload) { - return PendingPayloadHandle(); + if (result.has_error()) { + return {result.error()}; } - + std::unique_ptr internal_payload = std::move(result.value()); Payload::Id payload_id = internal_payload->GetId(); LOG(INFO) << "CreateIncomingPayload: payload_id=" << payload_id; pending_payloads_.StartTrackingPayload( @@ -757,7 +809,7 @@ PayloadManager::PendingPayloadHandle PayloadManager::CreateIncomingPayload( std::make_unique( std::move(internal_payload), EndpointIds{endpoint_id}, true, absl::bind_front(&PayloadManager::OnPendingPayloadDestroy, this))); - return pending_payloads_.GetPayload(payload_id); + return {pending_payloads_.GetPayload(payload_id)}; } void PayloadManager::OnPendingPayloadDestroy(const PendingPayload* payload) { @@ -776,13 +828,13 @@ void PayloadManager::OnPendingPayloadDestroy(const PendingPayload* payload) { void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( ClientProxy* client, const EndpointIds& finished_endpoint_ids, const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - location::nearby::proto::connections::PayloadStatus status) { + std::int64_t num_bytes_successfully_transferred, PayloadStatus status, + OperationResultCode operation_result_code) { RunOnStatusUpdateThread( "outgoing-payload-callbacks", [this, client, finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, - status]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { + num_bytes_successfully_transferred, status, + operation_result_code]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { // Make sure we're still tracking this payload. PendingPayloadHandle pending_payload = GetPayload(payload_header.id()); if (!pending_payload) { @@ -805,7 +857,13 @@ void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( // Mark this payload as done for analytics. client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_header.id(), status); + endpoint_id, payload_header.id(), status, + (operation_result_code == OperationResultCode::DETAIL_UNKNOWN && + status == PayloadStatus::ENDPOINT_IO_ERROR) + ? client->GetAnalyticsRecorder() + .GetChannelIoErrorResultCodeFromMedium( + client->GetConnectedMedium(endpoint_id)) + : operation_result_code); } // Remove these endpoints from our tracking list for this payload. @@ -821,12 +879,12 @@ void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( void PayloadManager::SendClientCallbacksForFinishedIncomingPayload( ClientProxy* client, const std::string& endpoint_id, const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, - location::nearby::proto::connections::PayloadStatus status) { + std::int64_t offset_bytes, PayloadStatus status, + OperationResultCode operation_result_code) { RunOnStatusUpdateThread( "incoming-payload-callbacks", - [this, client, endpoint_id, payload_header, offset_bytes, - status]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { + [this, client, endpoint_id, payload_header, offset_bytes, status, + operation_result_code]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { // Make sure we're still tracking this payload. PendingPayloadHandle pending_payload = GetPayload(payload_header.id()); if (!pending_payload) { @@ -845,7 +903,7 @@ void PayloadManager::SendClientCallbacksForFinishedIncomingPayload( // Analyze client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, payload_header.id(), status); + endpoint_id, payload_header.id(), status, operation_result_code); }); } @@ -918,10 +976,10 @@ bool PayloadManager::WaitForReceivedAck( // Local payload cancellation if (latest_pending_payload->IsLocallyCanceled()) { - HandleFinishedOutgoingPayload(client, {endpoint_id}, payload_header, - payload_chunk_offset, - location::nearby::proto::connections:: - PayloadStatus::LOCAL_CANCELLATION); + HandleFinishedOutgoingPayload( + client, {endpoint_id}, payload_header, payload_chunk_offset, + OperationResultCode::CLIENT_CANCELLATION_LOCAL_CANCEL_PAYLOAD, + PayloadStatus::LOCAL_CANCELLATION); LOG(INFO) << "[safe-to-disconnect] short-circuiting local " "payload cancellation for " << payload_header.id() << ", stop wait ack."; @@ -932,6 +990,7 @@ bool PayloadManager::WaitForReceivedAck( endpoint_info->status.Get())) { HandleFinishedOutgoingPayload( client, {endpoint_id}, payload_header, payload_chunk_offset, + OperationResultCode::CLIENT_CANCELLATION_REMOTE_CANCEL_PAYLOAD, EndpointInfoStatusToPayloadStatus(endpoint_info->status.Get())); LOG(INFO) << "[safe-to-disconnect] short-circuiting remote " "payload cancellation for " @@ -993,20 +1052,19 @@ void PayloadManager::HandleFinishedOutgoingPayload( ClientProxy* client, const EndpointIds& finished_endpoint_ids, const PayloadTransferFrame::PayloadHeader& payload_header, std::int64_t num_bytes_successfully_transferred, - location::nearby::proto::connections::PayloadStatus status) { + OperationResultCode operation_result_code, PayloadStatus status) { // This call will destroy a pending payload. SendClientCallbacksForFinishedOutgoingPayload( client, finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, status); + num_bytes_successfully_transferred, status, operation_result_code); switch (status) { - case location::nearby::proto::connections::PayloadStatus::LOCAL_ERROR: + case PayloadStatus::LOCAL_ERROR: SendControlMessage(finished_endpoint_ids, payload_header, num_bytes_successfully_transferred, PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); break; - case location::nearby::proto::connections::PayloadStatus:: - LOCAL_CANCELLATION: + case PayloadStatus::LOCAL_CANCELLATION: LOG(INFO) << "Sending PAYLOAD_CANCEL to receiver side; payload_id=" << payload_header.id(); SendControlMessage( @@ -1014,7 +1072,7 @@ void PayloadManager::HandleFinishedOutgoingPayload( num_bytes_successfully_transferred, PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); break; - case location::nearby::proto::connections::PayloadStatus::ENDPOINT_IO_ERROR: + case PayloadStatus::ENDPOINT_IO_ERROR: // Unregister these endpoints, since we had an IO error on the physical // connection. for (const auto& endpoint_id : finished_endpoint_ids) { @@ -1022,9 +1080,8 @@ void PayloadManager::HandleFinishedOutgoingPayload( DisconnectionReason::IO_ERROR); } break; - case location::nearby::proto::connections::PayloadStatus::REMOTE_ERROR: - case location::nearby::proto::connections::PayloadStatus:: - REMOTE_CANCELLATION: + case PayloadStatus::REMOTE_ERROR: + case PayloadStatus::REMOTE_CANCELLATION: // No special handling needed for these. break; default: @@ -1038,18 +1095,18 @@ void PayloadManager::HandleFinishedOutgoingPayload( void PayloadManager::HandleFinishedIncomingPayload( ClientProxy* client, const std::string& endpoint_id, const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, - location::nearby::proto::connections::PayloadStatus status) { - SendClientCallbacksForFinishedIncomingPayload( - client, endpoint_id, payload_header, offset_bytes, status); + std::int64_t offset_bytes, PayloadStatus status, + OperationResultCode operation_result_code) { + SendClientCallbacksForFinishedIncomingPayload(client, endpoint_id, + payload_header, offset_bytes, + status, operation_result_code); switch (status) { - case location::nearby::proto::connections::PayloadStatus::LOCAL_ERROR: + case PayloadStatus::LOCAL_ERROR: SendControlMessage({endpoint_id}, payload_header, offset_bytes, PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); break; - case location::nearby::proto::connections::PayloadStatus:: - LOCAL_CANCELLATION: + case PayloadStatus::LOCAL_CANCELLATION: SendControlMessage( {endpoint_id}, payload_header, offset_bytes, PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); @@ -1138,8 +1195,8 @@ void PayloadManager::HandleSuccessfulOutgoingChunk( if (is_last_chunk) { client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_header.id(), - location::nearby::proto::connections::SUCCESS); + endpoint_id, payload_header.id(), PayloadStatus::SUCCESS, + OperationResultCode::DETAIL_SUCCESS); // Stop tracking this endpoint. pending_payload->RemoveEndpoints({endpoint_id}); @@ -1235,8 +1292,8 @@ void PayloadManager::HandleSuccessfulIncomingChunk( if (is_last_chunk) { DestroyPendingPayload(payload_header.id()); client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, payload_header.id(), - location::nearby::proto::connections::SUCCESS); + endpoint_id, payload_header.id(), PayloadStatus::SUCCESS, + OperationResultCode::DETAIL_SUCCESS); } else { client->GetAnalyticsRecorder().OnPayloadChunkReceived( endpoint_id, payload_header.id(), payload_chunk_body_size); @@ -1286,18 +1343,33 @@ void PayloadManager::ProcessDataPacket( payload_header.total_size()); }); - pending_payload = + ErrorOr result = CreateIncomingPayload(payload_transfer_frame, from_endpoint_id); - if (!pending_payload) { + if (result.has_error()) { LOG(WARNING) << "PayloadManager failed to create InternalPayload from " "PayloadTransferFrame with payload_id=" << payload_header.id() << " and type " << payload_header.type() << ", aborting receipt."; + + // Analyticize. + OperationResultCode operation_result_code = + result.error().operation_result_code().value(); + RunOnStatusUpdateThread( + "process-data-packet", + [to_client, from_endpoint_id, payload_header, operation_result_code]() + RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { + to_client->GetAnalyticsRecorder().OnIncomingPayloadDone( + from_endpoint_id, payload_header.id(), + PayloadStatus::LOCAL_ERROR, operation_result_code); + }); + // Send the error to the remote endpoint. SendControlMessage({from_endpoint_id}, payload_header, payload_chunk.offset(), PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); return; + } else { + pending_payload = std::move(result.value()); } // Also, let the client know of this new incoming payload. RunOnStatusUpdateThread( @@ -1327,10 +1399,10 @@ void PayloadManager::ProcessDataPacket( // do all the cleanup. See go/nc-cancel-payload LOG(INFO) << "ProcessDataPacket: [cancel] endpoint_id=" << from_endpoint_id << "; payload_id=" << pending_payload->GetId(); - HandleFinishedIncomingPayload(to_client, from_endpoint_id, payload_header, - payload_chunk.offset(), - location::nearby::proto::connections:: - PayloadStatus::LOCAL_CANCELLATION); + HandleFinishedIncomingPayload( + to_client, from_endpoint_id, payload_header, payload_chunk.offset(), + PayloadStatus::LOCAL_CANCELLATION, + OperationResultCode::CLIENT_CANCELLATION_LOCAL_CANCEL_PAYLOAD); return; } @@ -1354,7 +1426,7 @@ void PayloadManager::ProcessDataPacket( << "; payload_id=" << pending_payload->GetId(); HandleFinishedIncomingPayload( to_client, from_endpoint_id, payload_header, payload_chunk.offset(), - location::nearby::proto::connections::PayloadStatus::LOCAL_ERROR); + PayloadStatus::LOCAL_ERROR, OperationResultCode::IO_FILE_WRITING_ERROR); return; } packet_meta_data.StopFileIo(); @@ -1404,7 +1476,8 @@ void PayloadManager::ProcessControlPacket( HandleFinishedIncomingPayload( to_client, from_endpoint_id, payload_header, control_message.offset(), - ControlMessageEventToPayloadStatus(control_message.event())); + ControlMessageEventToPayloadStatus(control_message.event()), + ControlMessageEventToOperationResultCode(control_message.event())); } else { LOG(INFO) << "Outgoing PAYLOAD_CANCELED: from endpoint_id=" << from_endpoint_id << "; self=" << this; @@ -1423,7 +1496,8 @@ void PayloadManager::ProcessControlPacket( HandleFinishedIncomingPayload( to_client, from_endpoint_id, payload_header, control_message.offset(), - ControlMessageEventToPayloadStatus(control_message.event())); + ControlMessageEventToPayloadStatus(control_message.event()), + ControlMessageEventToOperationResultCode(control_message.event())); } else { pending_payload->SetEndpointStatusFromControlMessage(from_endpoint_id, control_message); @@ -1480,14 +1554,14 @@ void PayloadManager::RecordPayloadStartedAnalytics( void PayloadManager::RecordInvalidPayloadAnalytics( ClientProxy* client, const EndpointIds& endpoint_ids, std::int64_t payload_id, PayloadType payload_type, std::int64_t offset, - std::int64_t total_size) { + std::int64_t total_size, OperationResultCode operation_result_code) { RecordPayloadStartedAnalytics(client, endpoint_ids, payload_id, payload_type, offset, total_size); for (const auto& endpoint_id : endpoint_ids) { client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_id, - location::nearby::proto::connections::LOCAL_ERROR); + endpoint_id, payload_id, PayloadStatus::LOCAL_ERROR, + operation_result_code); } } @@ -1665,8 +1739,7 @@ void PayloadManager::RunOnStatusUpdateThread( payload_status_update_executor_.Execute(name, std::move(runnable)); } -/////////////////////////////// PendingPayloads -////////////////////////////////// +/////////////////////////////// PendingPayloads //////////////////////////////// void PayloadManager::PendingPayloads::StartTrackingPayload( Payload::Id payload_id, std::unique_ptr pending_payload) { diff --git a/connections/implementation/payload_manager.h b/connections/implementation/payload_manager.h index a0da66d10b..3f4891788a 100644 --- a/connections/implementation/payload_manager.h +++ b/connections/implementation/payload_manager.h @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -40,12 +39,12 @@ #include "internal/platform/byte_array.h" #include "internal/platform/condition_variable.h" #include "internal/platform/count_down_latch.h" +#include "internal/platform/expected.h" #include "internal/platform/mutex.h" #include "internal/platform/single_thread_executor.h" namespace nearby { namespace connections { -using ::location::nearby::connections::PayloadTransferFrame; // Annotations for methods that need to run on PayloadStatusUpdateThread. // Use only in PayloadManager @@ -55,8 +54,7 @@ using ::location::nearby::connections::PayloadTransferFrame; class PayloadManager : public EndpointManager::FrameProcessor { public: using EndpointIds = std::vector; - constexpr static const absl::Duration kWaitCloseTimeout = - absl::Milliseconds(5000); + static constexpr absl::Duration kWaitCloseTimeout = absl::Milliseconds(5000); explicit PayloadManager(EndpointManager& endpoint_manager); ~PayloadManager() override; @@ -73,10 +71,11 @@ class PayloadManager : public EndpointManager::FrameProcessor { analytics::PacketMetaData& packet_meta_data) override; // @EndpointManagerThread - void OnEndpointDisconnect(ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - CountDownLatch barrier, - DisconnectionReason reason) override; + void OnEndpointDisconnect( + ClientProxy* client, const std::string& service_id, + const std::string& endpoint_id, CountDownLatch barrier, + location::nearby::proto::connections::DisconnectionReason reason) + override; void DisconnectFromEndpointManager(); @@ -94,10 +93,12 @@ class PayloadManager : public EndpointManager::FrameProcessor { }; void SetStatusFromControlMessage( - const PayloadTransferFrame::ControlMessage& control_message); + const location::nearby::connections::PayloadTransferFrame:: + ControlMessage& control_message); static Status ControlMessageEventToEndpointInfoStatus( - PayloadTransferFrame::ControlMessage::EventType event); + location::nearby::connections::PayloadTransferFrame::ControlMessage:: + EventType event); void MarkReceivedAckFromEndpoint(); bool IsEndpointAvailable(ClientProxy* clientProxy, EndpointInfo::Status status); @@ -153,8 +154,8 @@ class PayloadManager : public EndpointManager::FrameProcessor { // Sets the status for a particular endpoint. void SetEndpointStatusFromControlMessage( const std::string& endpoint_id, - const PayloadTransferFrame::ControlMessage& control_message) - ABSL_LOCKS_EXCLUDED(mutex_); + const location::nearby::connections::PayloadTransferFrame:: + ControlMessage& control_message) ABSL_LOCKS_EXCLUDED(mutex_); // Sets the offset for a particular endpoint. void SetOffsetForEndpoint(const std::string& endpoint_id, @@ -272,47 +273,61 @@ class PayloadManager : public EndpointManager::FrameProcessor { // Returns list of endpoint ids. static EndpointIds EndpointsToEndpointIds(const Endpoints& endpoints); - bool SendPayloadLoop(ClientProxy* client, PendingPayload& pending_payload, - PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t& next_chunk_offset, size_t resume_offset, - int index); + bool SendPayloadLoop( + ClientProxy* client, PendingPayload& pending_payload, + location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, + std::int64_t& next_chunk_offset, size_t resume_offset, int index); void SendClientCallbacksForFinishedIncomingPayloadRunnable( ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t offset_bytes, - location::nearby::proto::connections::PayloadStatus status); + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); // Converts the status of an endpoint that's been set out-of-band via a // remote ControlMessage to the PayloadStatus for handling of that // endpoint-payload pair. static location::nearby::proto::connections::PayloadStatus EndpointInfoStatusToPayloadStatus(EndpointInfo::Status status); + static location::nearby::proto::connections::OperationResultCode + EndpointInfoStatusToOperationResultCode(EndpointInfo::Status status); // Converts a ControlMessage::EventType for a particular payload to a // PayloadStatus. Called when we've received a ControlMessage with this // event from a remote endpoint; thus the PayloadStatuses are REMOTE_*. static location::nearby::proto::connections::PayloadStatus ControlMessageEventToPayloadStatus( - PayloadTransferFrame::ControlMessage::EventType event); + location::nearby::connections::PayloadTransferFrame::ControlMessage:: + EventType event); + static location::nearby::proto::connections::OperationResultCode + ControlMessageEventToOperationResultCode( + location::nearby::connections::PayloadTransferFrame::ControlMessage:: + EventType event); static PayloadProgressInfo::Status PayloadStatusToTransferUpdateStatus( location::nearby::proto::connections::PayloadStatus status); int GetOptimalChunkSize(EndpointIds endpoint_ids); - PayloadTransferFrame::PayloadHeader CreatePayloadHeader( - const InternalPayload& internal_payload, size_t offset, - const std::string& parent_folder, const std::string& file_name); + location::nearby::connections::PayloadTransferFrame::PayloadHeader + CreatePayloadHeader(const InternalPayload& internal_payload, size_t offset, + const std::string& parent_folder, + const std::string& file_name); - PayloadTransferFrame::PayloadChunk CreatePayloadChunk(std::int64_t offset, - ByteArray body, - int index); - bool IsLastChunk(PayloadTransferFrame::PayloadChunk payload_chunk) { + location::nearby::connections::PayloadTransferFrame::PayloadChunk + CreatePayloadChunk(std::int64_t offset, ByteArray body, int index); + bool IsLastChunk( + location::nearby::connections::PayloadTransferFrame::PayloadChunk + payload_chunk) { return ((payload_chunk.flags() & - PayloadTransferFrame::PayloadChunk::LAST_CHUNK) != 0); + location::nearby::connections::PayloadTransferFrame::PayloadChunk:: + LAST_CHUNK) != 0); } - PendingPayloadHandle CreateIncomingPayload(const PayloadTransferFrame& frame, - const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); + ErrorOr CreateIncomingPayload( + const location::nearby::connections::PayloadTransferFrame& frame, + const std::string& endpoint_id) ABSL_LOCKS_EXCLUDED(mutex_); Payload::Id CreateOutgoingPayload(Payload payload, const EndpointIds& endpoint_ids) @@ -320,20 +335,28 @@ class PayloadManager : public EndpointManager::FrameProcessor { void SendClientCallbacksForFinishedOutgoingPayload( ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t num_bytes_successfully_transferred, - location::nearby::proto::connections::PayloadStatus status); + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); void SendClientCallbacksForFinishedIncomingPayload( ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t offset_bytes, - location::nearby::proto::connections::PayloadStatus status); + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); void SendControlMessage( const EndpointIds& endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t num_bytes_successfully_transferred, - PayloadTransferFrame::ControlMessage::EventType event_type); + location::nearby::connections::PayloadTransferFrame::ControlMessage:: + EventType event_type); void SendPayloadReceivedAck(ClientProxy* client, PendingPayload& pending_payload, @@ -343,7 +366,8 @@ class PayloadManager : public EndpointManager::FrameProcessor { bool WaitForReceivedAck( ClientProxy* client, const std::string& endpoint_id, PendingPayload& pending_payload, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t payload_chunk_offset, bool is_last_chunk); bool IsPayloadReceivedAckEnabled(ClientProxy* client, const std::string& endpoint_id, @@ -353,37 +377,49 @@ class PayloadManager : public EndpointManager::FrameProcessor { // statuses except for SUCCESS are handled here. void HandleFinishedOutgoingPayload( ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t num_bytes_successfully_transferred, + location::nearby::proto::connections::OperationResultCode + operation_result_code, location::nearby::proto::connections::PayloadStatus status = location:: nearby::proto::connections::PayloadStatus::UNKNOWN_PAYLOAD_STATUS); void HandleFinishedIncomingPayload( ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int64_t offset_bytes, - location::nearby::proto::connections::PayloadStatus status); + location::nearby::proto::connections::PayloadStatus status, + location::nearby::proto::connections::OperationResultCode + operation_result_code); void HandleSuccessfulOutgoingChunk( ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, std::int64_t payload_chunk_body_size); void HandleSuccessfulIncomingChunk( ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, + const location::nearby::connections::PayloadTransferFrame::PayloadHeader& + payload_header, std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, std::int64_t payload_chunk_body_size); void ProcessDataPacket(ClientProxy* to_client, const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame, - Medium medium, + location::nearby::connections::PayloadTransferFrame& + payload_transfer_frame, + location::nearby::proto::connections::Medium medium, analytics::PacketMetaData& packet_meta_data); void ProcessControlPacket(ClientProxy* to_client, const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame); - void ProcessPayloadAckPacket(const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame); + location::nearby::connections::PayloadTransferFrame& + payload_transfer_frame); + void ProcessPayloadAckPacket( + const std::string& from_endpoint_id, + location::nearby::connections::PayloadTransferFrame& + payload_transfer_frame); void NotifyClientOfIncomingPayloadProgressInfo( ClientProxy* client, const std::string& endpoint_id, @@ -407,15 +443,16 @@ class PayloadManager : public EndpointManager::FrameProcessor { PayloadType payload_type, std::int64_t offset, std::int64_t total_size); - void RecordInvalidPayloadAnalytics(ClientProxy* client, - const EndpointIds& endpoint_ids, - std::int64_t payload_id, - PayloadType payload_type, - std::int64_t offset, - std::int64_t total_size); + void RecordInvalidPayloadAnalytics( + ClientProxy* client, const EndpointIds& endpoint_ids, + std::int64_t payload_id, PayloadType payload_type, std::int64_t offset, + std::int64_t total_size, + location::nearby::proto::connections::OperationResultCode + operation_result_code); PayloadType FramePayloadTypeToPayloadType( - PayloadTransferFrame::PayloadHeader::PayloadType type); + location::nearby::connections::PayloadTransferFrame::PayloadHeader:: + PayloadType type); void OnPendingPayloadDestroy(const PendingPayload* payload); mutable Mutex mutex_; diff --git a/connections/implementation/payload_manager_test.cc b/connections/implementation/payload_manager_test.cc index 797b0b162b..22d759f4d2 100644 --- a/connections/implementation/payload_manager_test.cc +++ b/connections/implementation/payload_manager_test.cc @@ -22,17 +22,16 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "connections/implementation/analytics/packet_meta_data.h" -#include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/simulation_user.h" #include "connections/listeners.h" #include "connections/medium_selector.h" #include "connections/payload.h" #include "connections/status.h" -#include "internal/flags/nearby_flags.h" #include "internal/platform/byte_array.h" #include "internal/platform/count_down_latch.h" #include "internal/platform/exception.h" +#include "internal/platform/input_stream.h" #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" #include "internal/platform/pipe.h" @@ -41,6 +40,7 @@ namespace nearby { namespace connections { namespace { using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::connections::PayloadTransferFrame; using ::nearby::analytics::PacketMetaData; using ::location::nearby::proto::connections::Medium; diff --git a/connections/implementation/reconnect_manager.cc b/connections/implementation/reconnect_manager.cc index 8da7c8c806..c560974947 100644 --- a/connections/implementation/reconnect_manager.cc +++ b/connections/implementation/reconnect_manager.cc @@ -41,6 +41,7 @@ #include "internal/platform/cancellation_flag_listener.h" #include "internal/platform/count_down_latch.h" #include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/system_clock.h" #include "internal/platform/logging.h" @@ -923,16 +924,17 @@ bool ReconnectManager::BluetoothImpl::ConnectOverMedium() { return false; } - bluetooth_socket_ = + ErrorOr bluetooth_socket_result = bluetooth_medium.Connect(remote_bluetooth_device, reconnect_service_id_, client_->GetCancellationFlag(endpoint_id_)); - if (!bluetooth_socket_.IsValid()) { + if (bluetooth_socket_result.has_error()) { LOG(ERROR) << "Failed to reconnect to Bluetooth device " << remote_bluetooth_device.GetName() << " for endpoint(id=" << endpoint_id_ << ")."; return false; } + bluetooth_socket_ = std::move(bluetooth_socket_result.value()); reconnect_channel_ = std::make_unique( UnWrapInitiatorReconnectServiceId(reconnect_service_id_), diff --git a/connections/implementation/service_controller_router_test.cc b/connections/implementation/service_controller_router_test.cc index 7d8599baa5..ca953b8301 100644 --- a/connections/implementation/service_controller_router_test.cc +++ b/connections/implementation/service_controller_router_test.cc @@ -89,7 +89,8 @@ class ServiceControllerRouterTest : public testing::Test { EXPECT_EQ(result_, Status{Status::kSuccess}); } client->StartedAdvertising(kServiceId, advertising_options.strategy, - info.listener, absl::MakeSpan(mediums_)); + info.listener, absl::MakeSpan(mediums_), + /*operation_result_with_medium=*/{}); EXPECT_TRUE(client->IsAdvertising()); } @@ -119,7 +120,8 @@ class ServiceControllerRouterTest : public testing::Test { EXPECT_EQ(result_, Status{Status::kSuccess}); } client->StartedDiscovery(service_id, discovery_options.strategy, - std::move(listener), absl::MakeSpan(mediums_)); + std::move(listener), absl::MakeSpan(mediums_), + /*operation_result_with_medium=*/{}); EXPECT_TRUE(client->IsDiscovering()); } diff --git a/connections/implementation/webrtc_bwu_handler.cc b/connections/implementation/webrtc_bwu_handler.cc index 8d2b0652bc..3b470f23ac 100644 --- a/connections/implementation/webrtc_bwu_handler.cc +++ b/connections/implementation/webrtc_bwu_handler.cc @@ -32,13 +32,19 @@ #include "connections/implementation/offline_frames.h" #include "connections/implementation/webrtc_endpoint_channel.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" namespace nearby { namespace connections { + +namespace { using ::location::nearby::connections::LocationHint; using ::location::nearby::connections::LocationStandard; +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace +// TODO(edwinwu): Add exact OperationResultCode for WebrtcBwuHandler. WebrtcBwuHandler::WebrtcIncomingSocket::WebrtcIncomingSocket( const std::string& name, mediums::WebRtcSocketWrapper socket) : name_(name), socket_(socket) {} @@ -54,7 +60,7 @@ WebrtcBwuHandler::WebrtcBwuHandler( // Called by BWU target. Retrieves a new medium info from incoming message, // and establishes connection over WebRTC using this info. -std::unique_ptr +ErrorOr> WebrtcBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { @@ -79,7 +85,7 @@ WebrtcBwuHandler::CreateUpgradedEndpointChannel( NEARBY_LOGS(ERROR) << "WebRtcBwuHandler failed to connect to remote peer (" << peer_id.GetId() << ") on endpoint " << endpoint_id << ", aborting upgrade."; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } NEARBY_LOGS(INFO) << "WebRtcBwuHandler successfully connected to remote " @@ -95,9 +101,10 @@ WebrtcBwuHandler::CreateUpgradedEndpointChannel( NEARBY_LOGS(ERROR) << "WebRtcBwuHandler failed to create new EndpointChannel for " "outgoing socket, aborting upgrade."; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } - return channel; + return {std::move(channel)}; } void WebrtcBwuHandler::HandleRevertInitiatorStateForService( diff --git a/connections/implementation/webrtc_bwu_handler.h b/connections/implementation/webrtc_bwu_handler.h index 97e6cf4408..8ad821b88d 100644 --- a/connections/implementation/webrtc_bwu_handler.h +++ b/connections/implementation/webrtc_bwu_handler.h @@ -19,6 +19,7 @@ #include #include +#include #include "connections/implementation/base_bwu_handler.h" #include "connections/implementation/bwu_handler.h" @@ -29,6 +30,7 @@ #include "connections/implementation/mediums/webrtc_socket.h" #include "connections/medium_selector.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -56,11 +58,14 @@ class WebrtcBwuHandler : public BaseBwuHandler { }; // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; - Medium GetUpgradeMedium() const final { return Medium::WEB_RTC; } + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; + location::nearby::proto::connections::Medium GetUpgradeMedium() const final { + return Medium::WEB_RTC; + } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {} diff --git a/connections/implementation/webrtc_bwu_handler_stub.cc b/connections/implementation/webrtc_bwu_handler_stub.cc index 91f19c1fd4..4bbb292f4b 100644 --- a/connections/implementation/webrtc_bwu_handler_stub.cc +++ b/connections/implementation/webrtc_bwu_handler_stub.cc @@ -25,10 +25,15 @@ #include "connections/implementation/mediums/webrtc_peer_id_stub.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/webrtc_endpoint_channel.h" +#include "internal/platform/expected.h" namespace nearby { namespace connections { +namespace { +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace + WebrtcBwuHandler::WebrtcIncomingSocket::WebrtcIncomingSocket( const std::string& name, mediums::WebRtcSocketWrapper socket) : name_(name), socket_(socket) {} @@ -44,11 +49,11 @@ WebrtcBwuHandler::WebrtcBwuHandler( // Called by BWU target. Retrieves a new medium info from incoming message, // and establishes connection over WebRTC using this info. -std::unique_ptr +ErrorOr> WebrtcBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } void WebrtcBwuHandler::HandleRevertInitiatorStateForService( diff --git a/connections/implementation/webrtc_bwu_handler_stub.h b/connections/implementation/webrtc_bwu_handler_stub.h index de0a9ff1fe..e3b0aebbbb 100644 --- a/connections/implementation/webrtc_bwu_handler_stub.h +++ b/connections/implementation/webrtc_bwu_handler_stub.h @@ -28,6 +28,7 @@ #else #include "connections/implementation/mediums/webrtc_socket.h" #endif +#include "internal/platform/expected.h" namespace nearby { namespace connections { @@ -55,11 +56,14 @@ class WebrtcBwuHandler : public BaseBwuHandler { }; // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; - Medium GetUpgradeMedium() const final { return Medium::WEB_RTC; } + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; + location::nearby::proto::connections::Medium GetUpgradeMedium() const final { + return Medium::WEB_RTC; + } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {} diff --git a/connections/implementation/wifi_direct_bwu_handler.cc b/connections/implementation/wifi_direct_bwu_handler.cc index 742aa002b7..e7e11157a1 100644 --- a/connections/implementation/wifi_direct_bwu_handler.cc +++ b/connections/implementation/wifi_direct_bwu_handler.cc @@ -15,7 +15,6 @@ #include "connections/implementation/wifi_direct_bwu_handler.h" #include -#include #include #include #include @@ -28,6 +27,7 @@ #include "connections/implementation/offline_frames.h" #include "connections/implementation/wifi_direct_endpoint_channel.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" #include "internal/platform/wifi_credential.h" #include "internal/platform/wifi_direct.h" @@ -35,6 +35,11 @@ namespace nearby { namespace connections { +namespace { +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace + +// TODO(edwinwu): Add exact OperationResultCode for WifiDirectBwuHandler. WifiDirectBwuHandler::WifiDirectBwuHandler( Mediums& mediums, IncomingConnectionCallback incoming_connection_callback) : BaseBwuHandler(std::move(incoming_connection_callback)), @@ -101,13 +106,13 @@ void WifiDirectBwuHandler::HandleRevertInitiatorStateForService( << "upgrade service ID " << upgrade_service_id; } -std::unique_ptr +ErrorOr> WifiDirectBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { if (!upgrade_path_info.has_wifi_direct_credentials()) { NEARBY_LOGS(INFO) << "No WifiDirect Credential"; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } const UpgradePathInfo::WifiDirectCredentials& upgrade_path_info_credentials = upgrade_path_info.wifi_direct_credentials(); @@ -123,7 +128,7 @@ WifiDirectBwuHandler::CreateUpgradedEndpointChannel( if (!wifi_direct_medium_.ConnectWifiDirect(ssid, password)) { NEARBY_LOGS(ERROR) << "Connect to WifiDiret GO failed"; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } WifiDirectSocket socket = wifi_direct_medium_.Connect( @@ -132,7 +137,7 @@ WifiDirectBwuHandler::CreateUpgradedEndpointChannel( NEARBY_LOGS(ERROR) << "WifiDirectBwuHandler failed to connect to the WifiDirect service(" << port << ") for endpoint " << endpoint_id; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } NEARBY_VLOG(1) @@ -140,8 +145,8 @@ WifiDirectBwuHandler::CreateUpgradedEndpointChannel( << port << ") while upgrading endpoint " << endpoint_id; // Create a new WifiDirectEndpointChannel. - return std::make_unique( - service_id, /*channel_name=*/service_id, socket); + return {std::make_unique( + service_id, /*channel_name=*/service_id, socket)}; } void WifiDirectBwuHandler::OnIncomingWifiDirectConnection( diff --git a/connections/implementation/wifi_direct_bwu_handler.h b/connections/implementation/wifi_direct_bwu_handler.h index e7f159ea23..c189b87d5f 100644 --- a/connections/implementation/wifi_direct_bwu_handler.h +++ b/connections/implementation/wifi_direct_bwu_handler.h @@ -19,8 +19,16 @@ #include #include "connections/implementation/base_bwu_handler.h" +#include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" #include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/mediums/wifi.h" +#include "connections/implementation/mediums/wifi_direct.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" +#include "internal/platform/wifi_direct.h" +#include "utility" namespace nearby { namespace connections { @@ -53,11 +61,14 @@ class WifiDirectBwuHandler : public BaseBwuHandler { // WFD protocol to established connection while WINRT follow the standard WFD // spec to achieve the connection. So return fail to stop the upgrade request // from phone side. - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; - Medium GetUpgradeMedium() const final { return Medium::WIFI_DIRECT; } + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; + location::nearby::proto::connections::Medium GetUpgradeMedium() const final { + return location::nearby::proto::connections::Medium::WIFI_DIRECT; + } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {} diff --git a/connections/implementation/wifi_direct_bwu_test.cc b/connections/implementation/wifi_direct_bwu_test.cc index b01d99981e..04d954128f 100644 --- a/connections/implementation/wifi_direct_bwu_test.cc +++ b/connections/implementation/wifi_direct_bwu_test.cc @@ -16,16 +16,28 @@ #include #include "gtest/gtest.h" +#include "absl/time/time.h" #include "connections/implementation/bwu_handler.h" +#include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/offline_frames.h" #include "connections/implementation/wifi_direct_bwu_handler.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/count_down_latch.h" +#include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" +#include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" +#include "internal/platform/single_thread_executor.h" namespace nearby { namespace connections { namespace { using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::proto::connections::OperationResultCode; constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); } // namespace @@ -97,17 +109,22 @@ TEST_F(WifiDirectTest, WFDGOBWUInit_GCCreateEndpointChannel) { auto bwu_frame = upgrade_frame.result().v1().bandwidth_upgrade_negotiation(); - std::unique_ptr new_channel = + ErrorOr> result = handler_2->CreateUpgradedEndpointChannel( &wifi_direct_gc, /*service_id=*/"A", /*endpoint_id=*/"1", bwu_frame.upgrade_path_info()); if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { + ASSERT_TRUE(result.has_value()); + std::unique_ptr new_channel = std::move(result.value()); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_EQ(new_channel->GetMedium(), location::nearby::proto::connections::Medium::WIFI_DIRECT); } else { + EXPECT_FALSE(result.has_value()); + EXPECT_TRUE(result.has_error()); + EXPECT_EQ(result.error().operation_result_code(), + OperationResultCode::DETAIL_UNKNOWN); accept_latch.CountDown(); - EXPECT_EQ(new_channel, nullptr); } EXPECT_TRUE(mediums_2.GetWifiDirect().IsConnectedToGO()); handler_2->RevertResponderState(/*service_id=*/"A"); diff --git a/connections/implementation/wifi_hotspot_bwu_handler.cc b/connections/implementation/wifi_hotspot_bwu_handler.cc index 4e8b124716..43171578e1 100644 --- a/connections/implementation/wifi_hotspot_bwu_handler.cc +++ b/connections/implementation/wifi_hotspot_bwu_handler.cc @@ -15,7 +15,6 @@ #include "connections/implementation/wifi_hotspot_bwu_handler.h" #include -#include #include #include #include @@ -25,11 +24,11 @@ #include "connections/implementation/client_proxy.h" #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/mediums/mediums.h" -#include "connections/implementation/mediums/utils.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/wifi_hotspot_endpoint_channel.h" #include "connections/strategy.h" #include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/logging.h" #include "internal/platform/wifi_credential.h" #include "internal/platform/wifi_hotspot.h" @@ -37,6 +36,11 @@ namespace nearby { namespace connections { +namespace { +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace + +// TODO(edwinwu): Add exact OperationResultCode for WifiHotspotBwuHandler. WifiHotspotBwuHandler::WifiHotspotBwuHandler( Mediums& mediums, IncomingConnectionCallback incoming_connection_callback) : BaseBwuHandler(std::move(incoming_connection_callback)), @@ -108,13 +112,13 @@ void WifiHotspotBwuHandler::HandleRevertInitiatorStateForService( // Called by BWU target. Retrieves a new medium info from incoming message, // and establishes connection over WifiHotspot using this info. -std::unique_ptr +ErrorOr> WifiHotspotBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { if (!upgrade_path_info.has_wifi_hotspot_credentials()) { NEARBY_LOGS(INFO) << "No Hotspot Credential"; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } const UpgradePathInfo::WifiHotspotCredentials& upgrade_path_info_credentials = upgrade_path_info.wifi_hotspot_credentials(); @@ -131,7 +135,7 @@ WifiHotspotBwuHandler::CreateUpgradedEndpointChannel( if (!wifi_hotspot_medium_.ConnectWifiHotspot(ssid, password, frequency)) { NEARBY_LOGS(ERROR) << "Connect to Hotspot failed"; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } WifiHotspotSocket socket = wifi_hotspot_medium_.Connect( @@ -140,7 +144,7 @@ WifiHotspotBwuHandler::CreateUpgradedEndpointChannel( NEARBY_LOGS(ERROR) << "WifiHotspotBwuHandler failed to connect to the WifiHotspot service(" << gateway << ":" << port << ") for endpoint " << endpoint_id; - return nullptr; + return {Error(OperationResultCode::DETAIL_UNKNOWN)}; } NEARBY_VLOG(1) @@ -151,7 +155,7 @@ WifiHotspotBwuHandler::CreateUpgradedEndpointChannel( auto channel = std::make_unique( service_id, /*channel_name=*/service_id, socket); - return channel; + return {std::move(channel)}; } // Accept Connection Callback. diff --git a/connections/implementation/wifi_hotspot_bwu_handler.h b/connections/implementation/wifi_hotspot_bwu_handler.h index 3e4fd611ce..f19f708d7e 100644 --- a/connections/implementation/wifi_hotspot_bwu_handler.h +++ b/connections/implementation/wifi_hotspot_bwu_handler.h @@ -15,12 +15,19 @@ #ifndef CORE_INTERNAL_WIFI_HOTSPOT_BWU_HANDLER_H_ #define CORE_INTERNAL_WIFI_HOTSPOT_BWU_HANDLER_H_ +#include #include +#include #include "connections/implementation/base_bwu_handler.h" +#include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" -#include "connections/implementation/endpoint_channel_manager.h" +#include "connections/implementation/endpoint_channel.h" #include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/mediums/wifi_hotspot.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" +#include "internal/platform/wifi_hotspot.h" namespace nearby { namespace connections { @@ -49,11 +56,14 @@ class WifiHotspotBwuHandler : public BaseBwuHandler { }; // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; - Medium GetUpgradeMedium() const final { return Medium::WIFI_HOTSPOT; } + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; + location::nearby::proto::connections::Medium GetUpgradeMedium() const final { + return location::nearby::proto::connections::Medium::WIFI_HOTSPOT; + } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {} diff --git a/connections/implementation/wifi_hotspot_bwu_test.cc b/connections/implementation/wifi_hotspot_bwu_test.cc index 091087c366..44a4733331 100644 --- a/connections/implementation/wifi_hotspot_bwu_test.cc +++ b/connections/implementation/wifi_hotspot_bwu_test.cc @@ -12,19 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include "gtest/gtest.h" +#include "absl/time/time.h" #include "connections/implementation/bwu_handler.h" +#include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/offline_frames.h" #include "connections/implementation/wifi_hotspot_bwu_handler.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/count_down_latch.h" +#include "internal/platform/exception.h" +#include "internal/platform/expected.h" #include "internal/platform/feature_flags.h" +#include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" +#include "internal/platform/single_thread_executor.h" namespace nearby { namespace connections { namespace { using ::location::nearby::connections::OfflineFrame; +using ::location::nearby::proto::connections::OperationResultCode; constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); } // namespace @@ -91,17 +104,22 @@ TEST_F(WifiHotspotTest, SoftAPBWUInit_STACreateEndpointChannel) { auto bwu_frame = upgrade_frame.result().v1().bandwidth_upgrade_negotiation(); - std::unique_ptr new_channel = + ErrorOr> result = handler_2->CreateUpgradedEndpointChannel(&client_2, /*service_id=*/"A", /*endpoint_id=*/"1", bwu_frame.upgrade_path_info()); if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { + ASSERT_TRUE(result.has_value()); + std::unique_ptr new_channel = std::move(result.value()); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); EXPECT_EQ(new_channel->GetMedium(), location::nearby::proto::connections::Medium::WIFI_HOTSPOT); } else { + EXPECT_FALSE(result.has_value()); + EXPECT_TRUE(result.has_error()); + EXPECT_EQ(result.error().operation_result_code(), + OperationResultCode::DETAIL_UNKNOWN); accept_latch.CountDown(); - EXPECT_EQ(new_channel, nullptr); } EXPECT_TRUE(mediums_2.GetWifiHotspot().IsConnectedToHotspot()); handler_2->RevertResponderState(/*service_id=*/"A"); diff --git a/connections/implementation/wifi_lan_bwu_handler.cc b/connections/implementation/wifi_lan_bwu_handler.cc index b1cb365065..22a7d6241c 100644 --- a/connections/implementation/wifi_lan_bwu_handler.cc +++ b/connections/implementation/wifi_lan_bwu_handler.cc @@ -14,13 +14,20 @@ #include "connections/implementation/wifi_lan_bwu_handler.h" +#include +#include #include #include #include "absl/functional/bind_front.h" +#include "connections/implementation/base_bwu_handler.h" #include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/mediums.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/wifi_lan_endpoint_channel.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" #include "internal/platform/implementation/wifi_utils.h" #include "internal/platform/logging.h" #include "internal/platform/wifi_lan.h" @@ -28,6 +35,10 @@ namespace nearby { namespace connections { +namespace { +using ::location::nearby::proto::connections::OperationResultCode; +} // namespace + WifiLanBwuHandler::WifiLanBwuHandler( Mediums& mediums, IncomingConnectionCallback incoming_connection_callback) : BaseBwuHandler(std::move(incoming_connection_callback)), @@ -35,19 +46,20 @@ WifiLanBwuHandler::WifiLanBwuHandler( // Called by BWU target. Retrieves a new medium info from incoming message, // and establishes connection over WifiLan using this info. -std::unique_ptr +ErrorOr> WifiLanBwuHandler::CreateUpgradedEndpointChannel( ClientProxy* client, const std::string& service_id, const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { if (!upgrade_path_info.has_wifi_lan_socket()) { - return nullptr; + return { + Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL)}; } const UpgradePathInfo::WifiLanSocket& upgrade_path_info_socket = upgrade_path_info.wifi_lan_socket(); if (!upgrade_path_info_socket.has_ip_address() || !upgrade_path_info_socket.has_wifi_port()) { NEARBY_LOGS(ERROR) << "WifiLanBwuHandler failed to parse UpgradePathInfo."; - return nullptr; + return {Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_IP_ADDRESS_ERROR)}; } const std::string& ip_address = upgrade_path_info_socket.ip_address(); @@ -57,14 +69,14 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( << "available WifiLan service (" << ip_address << ":" << port << ") for endpoint " << endpoint_id; - WifiLanSocket socket = wifi_lan_medium_.Connect( + ErrorOr socket_result = wifi_lan_medium_.Connect( service_id, ip_address, port, client->GetCancellationFlag(endpoint_id)); - if (!socket.IsValid()) { + if (socket_result.has_error()) { NEARBY_LOGS(ERROR) << "WifiLanBwuHandler failed to connect to the WifiLan service (" << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" << port << ") for endpoint " << endpoint_id; - return nullptr; + return {Error(socket_result.error().operation_result_code().value())}; } NEARBY_VLOG(1) @@ -74,16 +86,17 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( // Create a new WifiLanEndpointChannel. auto channel = std::make_unique( - service_id, /*channel_name=*/service_id, socket); + service_id, /*channel_name=*/service_id, socket_result.value()); if (channel == nullptr) { NEARBY_LOGS(ERROR) << "WifiLanBwuHandler failed to create WifiLan endpoint " << "channel to the WifiLan service (" << ip_address << ":" << port << ") for endpoint " << endpoint_id; - socket.Close(); - return nullptr; + socket_result.value().Close(); + return {Error( + OperationResultCode::NEARBY_LAN_ENDPOINT_CHANNEL_CREATION_FAILURE)}; } - return channel; + return {std::move(channel)}; } // Called by BWU initiator. Set up WifiLan upgraded medium for this endpoint, @@ -143,12 +156,12 @@ void WifiLanBwuHandler::HandleRevertInitiatorStateForService( void WifiLanBwuHandler::OnIncomingWifiLanConnection( ClientProxy* client, const std::string& upgrade_service_id, WifiLanSocket socket) { - auto channel = absl::make_unique( + auto channel = std::make_unique( upgrade_service_id, /*channel_name=*/upgrade_service_id, socket); std::unique_ptr connection( new IncomingSocketConnection{ - .socket = absl::make_unique(upgrade_service_id, - socket), + .socket = std::make_unique(upgrade_service_id, + socket), .channel = std::move(channel), }); NotifyOnIncomingConnection(client, std::move(connection)); diff --git a/connections/implementation/wifi_lan_bwu_handler.h b/connections/implementation/wifi_lan_bwu_handler.h index aee1ae01d0..64bad31035 100644 --- a/connections/implementation/wifi_lan_bwu_handler.h +++ b/connections/implementation/wifi_lan_bwu_handler.h @@ -15,12 +15,19 @@ #ifndef CORE_INTERNAL_WIFI_LAN_BWU_HANDLER_H_ #define CORE_INTERNAL_WIFI_LAN_BWU_HANDLER_H_ +#include #include +#include #include "connections/implementation/base_bwu_handler.h" +#include "connections/implementation/bwu_handler.h" #include "connections/implementation/client_proxy.h" -#include "connections/implementation/endpoint_channel_manager.h" +#include "connections/implementation/endpoint_channel.h" #include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/mediums/wifi_lan.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/expected.h" +#include "internal/platform/wifi_lan.h" namespace nearby { namespace connections { @@ -49,11 +56,14 @@ class WifiLanBwuHandler : public BaseBwuHandler { }; // BwuHandler implementation: - std::unique_ptr CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) final; - Medium GetUpgradeMedium() const final { return Medium::WIFI_LAN; } + ErrorOr> + CreateUpgradedEndpointChannel(ClientProxy* client, + const std::string& service_id, + const std::string& endpoint_id, + const UpgradePathInfo& upgrade_path_info) final; + location::nearby::proto::connections::Medium GetUpgradeMedium() const final { + return location::nearby::proto::connections::Medium::WIFI_LAN; + } void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id) final {}