mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Cleanup OutgoingTargetsManager.
PiperOrigin-RevId: 811928178
This commit is contained in:
committed by
Copybara-Service
parent
482d7f773d
commit
6922eea95f
+19
-2
@@ -269,16 +269,15 @@ cc_library(
|
||||
":thread_timer",
|
||||
":transfer_metadata",
|
||||
":types",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:types",
|
||||
"//proto:sharing_enums_cc_proto",
|
||||
"//sharing/analytics",
|
||||
"//sharing/certificates",
|
||||
"//sharing/flags/generated:generated_flags",
|
||||
"//sharing/internal/public:logging",
|
||||
"//sharing/proto:enums_cc_proto",
|
||||
"//sharing/proto:share_cc_proto",
|
||||
"//sharing/proto:wire_format_cc_proto",
|
||||
"@com_google_absl//absl/base:nullability",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/strings",
|
||||
@@ -940,3 +939,21 @@ cc_test(
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "outgoing_targets_manager_test",
|
||||
srcs = ["outgoing_targets_manager_test.cc"],
|
||||
deps = [
|
||||
":outgoing_targets_manager",
|
||||
":share_session",
|
||||
":test_support",
|
||||
":transfer_metadata",
|
||||
":types",
|
||||
"//internal/platform/implementation:platform_impl",
|
||||
"//internal/test",
|
||||
"//sharing/analytics",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace nearby::sharing {
|
||||
namespace {
|
||||
|
||||
using BlockedVendorId = ::nearby::sharing::Advertisement::BlockedVendorId;
|
||||
using ::absl::Milliseconds;
|
||||
using ::location::nearby::proto::sharing::OSType;
|
||||
using ::location::nearby::proto::sharing::ResponseToIntroduction;
|
||||
using ::location::nearby::proto::sharing::SessionStatus;
|
||||
@@ -239,9 +240,13 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
|
||||
outgoing_targets_manager_(
|
||||
context->GetClock(), service_thread_.get(),
|
||||
nearby_connections_manager_.get(), &analytics_recorder_,
|
||||
absl::bind_front(
|
||||
&NearbySharingServiceImpl::NotifyShareTargetDiscovered, this),
|
||||
absl::bind_front(&NearbySharingServiceImpl::NotifyShareTargetUpdated,
|
||||
this),
|
||||
absl::bind_front(&NearbySharingServiceImpl::NotifyShareTargetLost,
|
||||
this),
|
||||
absl::bind_front(&NearbySharingServiceImpl::OnOutgoingTransferUpdate,
|
||||
this)) {
|
||||
CHECK(nearby_connections_manager_);
|
||||
CHECK(analytics_recorder);
|
||||
@@ -1608,10 +1613,11 @@ void NearbySharingServiceImpl::HandleEndpointLost(
|
||||
|
||||
discovered_advertisements_to_retry_map_.erase(endpoint_id);
|
||||
discovered_advertisements_retried_set_.erase(endpoint_id);
|
||||
outgoing_targets_manager_.MoveToDiscoveryCache(std::string(endpoint_id),
|
||||
NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kDiscoveryCacheLostExpiryMs));
|
||||
outgoing_targets_manager_.OnShareTargetLost(
|
||||
std::string(endpoint_id),
|
||||
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kDiscoveryCacheLostExpiryMs)));
|
||||
FinishEndpointDiscoveryEvent();
|
||||
}
|
||||
|
||||
@@ -1703,53 +1709,8 @@ void NearbySharingServiceImpl::OnOutgoingDecryptedCertificate(
|
||||
return;
|
||||
}
|
||||
LogShareTargetDiscovered(*share_target);
|
||||
if (outgoing_targets_manager_.FindDuplicateInOutgoingShareTargets(
|
||||
endpoint_id, *share_target)) {
|
||||
outgoing_targets_manager_.DeduplicateInOutgoingShareTarget(
|
||||
*share_target, endpoint_id, std::move(certificate));
|
||||
FinishEndpointDiscoveryEvent();
|
||||
return;
|
||||
}
|
||||
bool in_discovery_cache =
|
||||
outgoing_targets_manager_.FindDuplicateInDiscoveryCache(endpoint_id,
|
||||
*share_target);
|
||||
VLOG(1) << __func__ << ": Adding (endpoint_id=" << endpoint_id
|
||||
<< ", share_target_id=" << share_target->id
|
||||
<< ") to outgoing share target map";
|
||||
outgoing_targets_manager_.CreateOutgoingShareSession(
|
||||
*share_target, endpoint_id, std::move(certificate),
|
||||
absl::bind_front(&NearbySharingServiceImpl::OnOutgoingTransferUpdate,
|
||||
this));
|
||||
if (in_discovery_cache) {
|
||||
NotifyShareTargetUpdated(*share_target);
|
||||
|
||||
LOG(INFO)
|
||||
<< __func__
|
||||
<< ": [Dedupped] Reported NotifyShareTargetUpdated to all surfaces "
|
||||
"for share_target: "
|
||||
<< share_target->ToString();
|
||||
FinishEndpointDiscoveryEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the endpoint id for the share target.
|
||||
LOG(INFO) << __func__ << ": An endpoint: " << endpoint_id
|
||||
<< " has been discovered, with an advertisement "
|
||||
"containing a valid share target with id: "
|
||||
<< share_target->id;
|
||||
|
||||
// Notifies the user that we discovered a device.
|
||||
VLOG(1) << __func__ << ": There are "
|
||||
<< (foreground_send_surface_map_.size() +
|
||||
background_send_surface_map_.size())
|
||||
<< " discovery callbacks be called.";
|
||||
|
||||
NotifyShareTargetDiscovered(*share_target);
|
||||
|
||||
VLOG(1) << __func__ << ": NotifyShareTargetDiscovered: share_target: "
|
||||
<< share_target->ToString() << " endpoint_id=" << endpoint_id
|
||||
<< " to all send surfaces.";
|
||||
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
*share_target, endpoint_id, std::move(certificate));
|
||||
FinishEndpointDiscoveryEvent();
|
||||
}
|
||||
|
||||
@@ -2070,7 +2031,10 @@ void NearbySharingServiceImpl::StartScanning() {
|
||||
is_scanning_ = true;
|
||||
InvalidateReceiveSurfaceState();
|
||||
|
||||
outgoing_targets_manager_.DisableAllOutgoingShareTargets();
|
||||
outgoing_targets_manager_.AllTargetsLost(
|
||||
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kDiscoveryCacheLostExpiryMs)));
|
||||
discovered_advertisements_to_retry_map_.clear();
|
||||
discovered_advertisements_retried_set_.clear();
|
||||
|
||||
@@ -3093,21 +3057,22 @@ void NearbySharingServiceImpl::UnregisterShareTarget(int64_t share_target_id) {
|
||||
// Find the endpoint id that matches the given share target.
|
||||
OutgoingShareSession* session =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(share_target_id);
|
||||
absl::Duration cache_retention =
|
||||
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kUnregisterTargetDiscoveryCacheLostExpiryMs));
|
||||
if (session != nullptr) {
|
||||
LOG(INFO) << __func__ << ": [Dedupped] Move the endpoint "
|
||||
<< session->endpoint_id() << " to discovery_cache.";
|
||||
outgoing_targets_manager_.MoveToDiscoveryCache(
|
||||
session->endpoint_id(),
|
||||
NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kUnregisterTargetDiscoveryCacheLostExpiryMs));
|
||||
outgoing_targets_manager_.OnShareTargetLost(
|
||||
session->endpoint_id(), cache_retention);
|
||||
} else {
|
||||
// Be careful not to clear out the share session map if a new session
|
||||
// was started during the cancellation delay.
|
||||
if (!is_scanning_ && !is_transferring_) {
|
||||
LOG(INFO) << "Cannot find session for target " << share_target_id
|
||||
<< " clearing all outgoing sessions.";
|
||||
outgoing_targets_manager_.DisableAllOutgoingShareTargets();
|
||||
outgoing_targets_manager_.AllTargetsLost(cache_retention);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022-2023 Google LLC
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,22 +16,22 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/clock.h"
|
||||
#include "internal/platform/task_runner.h"
|
||||
#include "proto/sharing_enums.pb.h"
|
||||
#include "sharing/analytics/analytics_recorder.h"
|
||||
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
|
||||
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
|
||||
#include "sharing/internal/public/logging.h"
|
||||
#include "sharing/nearby_connections_manager.h"
|
||||
#include "sharing/outgoing_share_session.h"
|
||||
@@ -45,20 +45,71 @@
|
||||
namespace nearby::sharing {
|
||||
|
||||
OutgoingTargetsManager::OutgoingTargetsManager(
|
||||
Clock* clock, TaskRunner* service_thread,
|
||||
NearbyConnectionsManager* connections_manager,
|
||||
Clock* absl_nonnull clock, TaskRunner* absl_nonnull service_thread,
|
||||
NearbyConnectionsManager* absl_nonnull connections_manager,
|
||||
analytics::AnalyticsRecorder* analytics_recorder,
|
||||
absl::AnyInvocable<void(const ShareTarget&)>
|
||||
share_target_discovered_callback,
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_updated_callback,
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_lost_callback)
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_lost_callback,
|
||||
std::function<void(OutgoingShareSession& session,
|
||||
const TransferMetadata& metadata)>
|
||||
transfer_update_callback)
|
||||
: clock_(*clock),
|
||||
service_thread_(*service_thread),
|
||||
connections_manager_(*connections_manager),
|
||||
analytics_recorder_(*analytics_recorder),
|
||||
share_target_discovered_callback_(
|
||||
std::move(share_target_discovered_callback)),
|
||||
share_target_updated_callback_(std::move(share_target_updated_callback)),
|
||||
share_target_lost_callback_(std::move(share_target_lost_callback)) {}
|
||||
share_target_lost_callback_(std::move(share_target_lost_callback)),
|
||||
transfer_update_callback_(std::move(transfer_update_callback)) {}
|
||||
|
||||
void OutgoingTargetsManager::OnShareTargetDiscovered(
|
||||
ShareTarget share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
|
||||
if (FindDuplicateInOutgoingShareTargets(endpoint_id, share_target)) {
|
||||
if (DeduplicateInOutgoingShareTarget(share_target, endpoint_id,
|
||||
std::move(certificate))) {
|
||||
share_target_updated_callback_(share_target);
|
||||
|
||||
void OutgoingTargetsManager::DeduplicateInOutgoingShareTarget(
|
||||
LOG(INFO) << __func__
|
||||
<< ": [Dedupped] NotifyShareTargetUpdated to all surfaces "
|
||||
"for share_target: "
|
||||
<< share_target.ToString();
|
||||
}
|
||||
return;
|
||||
}
|
||||
bool in_discovery_cache =
|
||||
FindDuplicateInDiscoveryCache(endpoint_id, share_target);
|
||||
VLOG(1) << __func__ << ": Adding (endpoint_id=" << endpoint_id
|
||||
<< ", share_target_id=" << share_target.id
|
||||
<< ") to outgoing share target map";
|
||||
CreateOutgoingShareSession(share_target, endpoint_id, std::move(certificate));
|
||||
if (in_discovery_cache) {
|
||||
share_target_updated_callback_(share_target);
|
||||
|
||||
LOG(INFO)
|
||||
<< __func__
|
||||
<< ": [Dedupped] Reported NotifyShareTargetUpdated to all surfaces "
|
||||
"for share_target: "
|
||||
<< share_target.ToString();
|
||||
return;
|
||||
}
|
||||
// Update the endpoint id for the share target.
|
||||
LOG(INFO) << __func__ << ": An endpoint: " << endpoint_id
|
||||
<< " has been discovered, with an advertisement "
|
||||
"containing a valid share target with id: "
|
||||
<< share_target.id;
|
||||
|
||||
share_target_discovered_callback_(share_target);
|
||||
|
||||
VLOG(1) << __func__ << ": NotifyShareTargetDiscovered: share_target: "
|
||||
<< share_target.ToString() << " endpoint_id=" << endpoint_id
|
||||
<< " to all send surfaces.";
|
||||
}
|
||||
|
||||
bool OutgoingTargetsManager::DeduplicateInOutgoingShareTarget(
|
||||
const ShareTarget& share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
|
||||
// TODO(b/343764269): may need to update last_outgoing_metadata_ if the
|
||||
@@ -70,22 +121,16 @@ void OutgoingTargetsManager::DeduplicateInOutgoingShareTarget(
|
||||
if (session_it == outgoing_share_session_map_.end()) {
|
||||
LOG(WARNING) << __func__ << ": share_target.id=" << share_target.id
|
||||
<< " not found in outgoing share session map.";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (session_it->second.IsConnected()) {
|
||||
LOG(INFO) << __func__ << ": share_target.id=" << share_target.id
|
||||
<< " is connected, not updating outgoing_share_session_map_.";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
session_it->second.UpdateSessionForDedup(share_target, std::move(certificate),
|
||||
endpoint_id);
|
||||
|
||||
share_target_updated_callback_(share_target);
|
||||
|
||||
LOG(INFO) << __func__
|
||||
<< ": [Dedupped] NotifyShareTargetUpdated to all surfaces "
|
||||
"for share_target: "
|
||||
<< share_target.ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OutgoingTargetsManager::FindDuplicateInDiscoveryCache(
|
||||
@@ -190,10 +235,10 @@ OutgoingTargetsManager::RemoveOutgoingShareTargetWithEndpointId(
|
||||
|
||||
// Pass endpoint_id by value here since we remove entries from the
|
||||
// outgoing_share_target_map_ in this function, and some callers like
|
||||
// DisableAllOutgoingShareTargets pass the map item key as the endpoint_id.
|
||||
// AllTargetsLost pass the map item key as the endpoint_id.
|
||||
// This prevents the endpoint_id from being invalidated in this function.
|
||||
void OutgoingTargetsManager::MoveToDiscoveryCache(std::string endpoint_id,
|
||||
uint64_t expiry_ms) {
|
||||
void OutgoingTargetsManager::OnShareTargetLost(std::string endpoint_id,
|
||||
absl::Duration retention) {
|
||||
std::optional<ShareTarget> share_target_opt =
|
||||
RemoveOutgoingShareTargetWithEndpointId(endpoint_id);
|
||||
if (!share_target_opt.has_value()) {
|
||||
@@ -205,8 +250,7 @@ void OutgoingTargetsManager::MoveToDiscoveryCache(std::string endpoint_id,
|
||||
cache_entry.share_target.receive_disabled = true;
|
||||
cache_entry.expiry_timer = std::make_unique<ThreadTimer>(
|
||||
service_thread_, absl::StrCat("discovery_cache_timeout_", endpoint_id),
|
||||
absl::Milliseconds(expiry_ms),
|
||||
[this, expiry_ms, endpoint_id = std::string(endpoint_id)]() {
|
||||
retention, [this, retention, endpoint_id]() {
|
||||
auto cache_node = discovery_cache_.extract(endpoint_id);
|
||||
if (cache_node.empty()) {
|
||||
LOG(WARNING) << "Trying to remove endpoint_id: " << endpoint_id
|
||||
@@ -216,14 +260,9 @@ void OutgoingTargetsManager::MoveToDiscoveryCache(std::string endpoint_id,
|
||||
ShareTarget& share_target = cache_node.mapped().share_target;
|
||||
LOG(INFO) << ": Removing (endpoint_id=" << endpoint_id
|
||||
<< ", share_target.id=" << share_target.id
|
||||
<< ") from discovery_cache after " << expiry_ms << "ms";
|
||||
<< ") from discovery_cache after " << retention;
|
||||
|
||||
share_target_lost_callback_(share_target);
|
||||
|
||||
VLOG(1) << "discovery_cache entry: " << endpoint_id << " timeout after "
|
||||
<< expiry_ms << "ms"
|
||||
<< ": [Dedupped] NotifyShareTargetLost to all surfaces for "
|
||||
<< "share_target: " << share_target.ToString();
|
||||
});
|
||||
// Send ShareTarget update to set receive disabled to true.
|
||||
share_target_updated_callback_(cache_entry.share_target);
|
||||
@@ -235,15 +274,12 @@ void OutgoingTargetsManager::MoveToDiscoveryCache(std::string endpoint_id,
|
||||
|
||||
void OutgoingTargetsManager::CreateOutgoingShareSession(
|
||||
const ShareTarget& share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate,
|
||||
absl::AnyInvocable<void(OutgoingShareSession& session,
|
||||
const TransferMetadata& metadata)>
|
||||
transfer_update_callback) {
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
|
||||
outgoing_share_target_map_.insert_or_assign(endpoint_id, share_target);
|
||||
auto [it_out, inserted] = outgoing_share_session_map_.try_emplace(
|
||||
share_target.id, &clock_, service_thread_, &connections_manager_,
|
||||
analytics_recorder_, std::string(endpoint_id), share_target,
|
||||
std::move(transfer_update_callback));
|
||||
transfer_update_callback_);
|
||||
if (!inserted) {
|
||||
LOG(WARNING) << __func__ << ": share_target.id=" << share_target.id
|
||||
<< " already exists in outgoing share session map. This "
|
||||
@@ -266,13 +302,10 @@ OutgoingShareSession* OutgoingTargetsManager::GetOutgoingShareSession(
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
void OutgoingTargetsManager::DisableAllOutgoingShareTargets() {
|
||||
void OutgoingTargetsManager::AllTargetsLost(absl::Duration retention) {
|
||||
VLOG(1) << "Move all outgoing share targets to discovery cache.";
|
||||
while (!outgoing_share_target_map_.empty()) {
|
||||
MoveToDiscoveryCache(outgoing_share_target_map_.begin()->first,
|
||||
NearbyFlags::GetInstance().GetInt64Flag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kUnregisterTargetDiscoveryCacheLostExpiryMs));
|
||||
OnShareTargetLost(outgoing_share_target_map_.begin()->first, retention);
|
||||
}
|
||||
DCHECK(outgoing_share_target_map_.empty());
|
||||
DCHECK(outgoing_share_session_map_.empty());
|
||||
@@ -280,8 +313,10 @@ void OutgoingTargetsManager::DisableAllOutgoingShareTargets() {
|
||||
|
||||
void OutgoingTargetsManager::Cleanup() {
|
||||
while (!outgoing_share_target_map_.empty()) {
|
||||
RemoveOutgoingShareTargetWithEndpointId(
|
||||
outgoing_share_target_map_.begin()->first);
|
||||
// Latch endpoint_id here since RemoveOutgoingShareTargetWithEndpointId()
|
||||
// will remove the entry from the map.
|
||||
std::string endpoint_id = outgoing_share_target_map_.begin()->first;
|
||||
RemoveOutgoingShareTargetWithEndpointId(endpoint_id);
|
||||
}
|
||||
discovery_cache_.clear();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022-2023 Google LLC
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,13 +18,16 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/clock.h"
|
||||
#include "internal/platform/task_runner.h"
|
||||
#include "proto/sharing_enums.pb.h"
|
||||
@@ -39,64 +42,82 @@
|
||||
#include "sharing/transfer_metadata.h"
|
||||
|
||||
namespace nearby::sharing {
|
||||
class NearbyShareContactManager;
|
||||
|
||||
namespace NearbySharingServiceUnitTests {
|
||||
class NearbySharingServiceImplTest_CreateShareTarget_Test;
|
||||
class NearbySharingServiceImplTest_RemoveIncomingPayloads_Test;
|
||||
}; // namespace NearbySharingServiceUnitTests
|
||||
|
||||
// Manages outgoing share targets and outgoing share sessions.
|
||||
//
|
||||
// This class is thread-compatible. All methods must be called on the service
|
||||
// thread.
|
||||
//
|
||||
// Each discovered share target has a corresponding outgoing share session.
|
||||
// When the share target is lost, the share target is moved to the
|
||||
// discovery cache and the share session is destroyed. The lost share target
|
||||
// is reported as receive_disabled. After a retention period, the share target
|
||||
// is removed from the discovery cache.
|
||||
// Newly discovered share targets that match share targets in the discovery
|
||||
// cache are merged with the discovery cache entry and a new share session is
|
||||
// created. The share target is then removed from the discovery cache and
|
||||
// reported as receive_enabled.
|
||||
class OutgoingTargetsManager {
|
||||
public:
|
||||
OutgoingTargetsManager(
|
||||
Clock* clock, TaskRunner* service_thread,
|
||||
NearbyConnectionsManager* connections_manager,
|
||||
analytics::AnalyticsRecorder* analytics_recorder,
|
||||
Clock* absl_nonnull clock, TaskRunner* absl_nonnull service_thread,
|
||||
NearbyConnectionsManager* absl_nonnull connections_manager,
|
||||
analytics::AnalyticsRecorder* absl_nonnull analytics_recorder,
|
||||
absl::AnyInvocable<void(const ShareTarget&)>
|
||||
share_target_discovered_callback,
|
||||
absl::AnyInvocable<void(const ShareTarget&)>
|
||||
share_target_updated_callback,
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_lost_callback);
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_lost_callback,
|
||||
std::function<void(OutgoingShareSession& session,
|
||||
const TransferMetadata& metadata)>
|
||||
transfer_update_callback);
|
||||
|
||||
// Remove all outgoing share targets and outgoing share sessions.
|
||||
// Share targets callbacks will not be called.
|
||||
// Any connected sessions will be disconnected.
|
||||
void Cleanup();
|
||||
|
||||
OutgoingShareSession* GetOutgoingShareSession(int64_t share_target_id);
|
||||
|
||||
// Update the entry in outgoing_share_session_map_ with the new share target
|
||||
// and OnShareTargetUpdated is called.
|
||||
void DeduplicateInOutgoingShareTarget(
|
||||
const ShareTarget& share_target, absl::string_view endpoint_id,
|
||||
void OnShareTargetDiscovered(
|
||||
ShareTarget share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate);
|
||||
|
||||
// Looks for a duplicate of the share target in the discovery cache.
|
||||
// If found, the share target is removed from the discovery cache and its
|
||||
// id is copied into `share_target`.
|
||||
// Returns true if the duplicate is found.
|
||||
bool FindDuplicateInDiscoveryCache(absl::string_view endpoint_id,
|
||||
ShareTarget& share_target);
|
||||
// Move the endpoint to the discovery cache and report the share target as
|
||||
// receive_disabled.
|
||||
// `retention` is the time to keep the share target in the discovery cache.
|
||||
void OnShareTargetLost(std::string endpoint_id, absl::Duration retention);
|
||||
|
||||
// Call OnShareTargetLost() on all known share targets.
|
||||
void AllTargetsLost(absl::Duration retention);
|
||||
|
||||
void ForEachShareTarget(
|
||||
absl::AnyInvocable<void(const ShareTarget&)> callback);
|
||||
|
||||
private:
|
||||
// Looks for a duplicate of the share target in the outgoing share
|
||||
// target map. The share target's id is changed to match an existing target if
|
||||
// available. Returns true if the duplicate is found.
|
||||
bool FindDuplicateInOutgoingShareTargets(absl::string_view endpoint_id,
|
||||
ShareTarget& share_target);
|
||||
|
||||
// Move the endpoint to the discovery cache with the given expiry time.
|
||||
void MoveToDiscoveryCache(std::string endpoint_id, uint64_t expiry_ms);
|
||||
// Update the entry in outgoing_share_session_map_ with the new share target.
|
||||
// Returns true if the share target was updated.
|
||||
bool DeduplicateInOutgoingShareTarget(
|
||||
const ShareTarget& share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate);
|
||||
|
||||
// Move all outgoing share targets to the discovery cache so that they will be
|
||||
// reported as receive_disabled.
|
||||
void DisableAllOutgoingShareTargets();
|
||||
// Looks for a duplicate of the share target in the discovery cache.
|
||||
// If found, the share target is removed from the discovery cache and its
|
||||
// id is copied into `share_target`.
|
||||
// Returns true if the duplicate is found.
|
||||
bool FindDuplicateInDiscoveryCache(absl::string_view endpoint_id,
|
||||
ShareTarget& share_target);
|
||||
|
||||
void CreateOutgoingShareSession(
|
||||
const ShareTarget& share_target, absl::string_view endpoint_id,
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate,
|
||||
absl::AnyInvocable<void(OutgoingShareSession& session,
|
||||
const TransferMetadata& metadata)>
|
||||
transfer_update_callback);
|
||||
std::optional<NearbyShareDecryptedPublicCertificate> certificate);
|
||||
|
||||
void ForEachShareTarget(
|
||||
absl::AnyInvocable<void(const ShareTarget&)> callback);
|
||||
|
||||
private:
|
||||
// Returns the share target if it has been removed, std::nullopt otherwise.
|
||||
std::optional<ShareTarget> RemoveOutgoingShareTargetWithEndpointId(
|
||||
absl::string_view endpoint_id);
|
||||
@@ -113,9 +134,13 @@ class OutgoingTargetsManager {
|
||||
TaskRunner& service_thread_;
|
||||
NearbyConnectionsManager& connections_manager_;
|
||||
analytics::AnalyticsRecorder& analytics_recorder_;
|
||||
absl::AnyInvocable<void(const ShareTarget&)>
|
||||
share_target_discovered_callback_;
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_updated_callback_;
|
||||
absl::AnyInvocable<void(const ShareTarget&)> share_target_lost_callback_;
|
||||
|
||||
std::function<void(OutgoingShareSession& session,
|
||||
const TransferMetadata& metadata)>
|
||||
transfer_update_callback_;
|
||||
// A map of endpoint id to ShareTarget, where each ShareTarget entry
|
||||
// directly corresponds to a OutgoingShareSession entry in
|
||||
// outgoing_share_target_info_map_;
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sharing/outgoing_targets_manager.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/test/fake_clock.h"
|
||||
#include "internal/test/fake_task_runner.h"
|
||||
#include "sharing/analytics/analytics_recorder.h"
|
||||
#include "sharing/fake_nearby_connections_manager.h"
|
||||
#include "sharing/outgoing_share_session.h"
|
||||
#include "sharing/share_target.h"
|
||||
#include "sharing/transfer_metadata.h"
|
||||
|
||||
namespace nearby::sharing {
|
||||
namespace {
|
||||
using ::absl::Seconds;
|
||||
using ::testing::InSequence;
|
||||
|
||||
class OutgoingTargetsManagerTest : public ::testing::Test {
|
||||
protected:
|
||||
OutgoingTargetsManagerTest()
|
||||
: service_thread_(&clock_, /*count=*/1),
|
||||
analytics_recorder_(/*vendor_id=*/0,
|
||||
/*event_logger=*/nullptr),
|
||||
outgoing_targets_manager_(
|
||||
&clock_, &service_thread_, &connections_manager_,
|
||||
&analytics_recorder_,
|
||||
share_target_discovered_callback_.AsStdFunction(),
|
||||
share_target_updated_callback_.AsStdFunction(),
|
||||
share_target_lost_callback_.AsStdFunction(),
|
||||
transfer_update_callback_.AsStdFunction()) {}
|
||||
|
||||
FakeClock clock_;
|
||||
FakeTaskRunner service_thread_;
|
||||
FakeNearbyConnectionsManager connections_manager_;
|
||||
analytics::AnalyticsRecorder analytics_recorder_;
|
||||
testing::MockFunction<void(const ShareTarget&)>
|
||||
share_target_discovered_callback_;
|
||||
testing::MockFunction<void(const ShareTarget&)>
|
||||
share_target_updated_callback_;
|
||||
testing::MockFunction<void(const ShareTarget&)> share_target_lost_callback_;
|
||||
testing::MockFunction<void(OutgoingShareSession&, const TransferMetadata&)>
|
||||
transfer_update_callback_;
|
||||
OutgoingTargetsManager outgoing_targets_manager_;
|
||||
};
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargetDiscoveredNewTarget) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr absl::string_view kEndpointId = "endpoint_id";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call).Times(0);
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId, /*certificate=*/std::nullopt);
|
||||
|
||||
OutgoingShareSession* session =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session, nullptr);
|
||||
EXPECT_EQ(session->share_target(), target);
|
||||
EXPECT_EQ(session->endpoint_id(), kEndpointId);
|
||||
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
}
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargetLost) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr absl::string_view kEndpointId = "endpoint_id";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
ShareTarget disabled_target = target;
|
||||
disabled_target.receive_disabled = true;
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call)
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, disabled_target);
|
||||
});
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(1);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
}
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId, /*certificate=*/std::nullopt);
|
||||
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
|
||||
outgoing_targets_manager_.OnShareTargetLost(std::string(kEndpointId),
|
||||
Seconds(10));
|
||||
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, disabled_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
|
||||
// Retention timer expired.
|
||||
clock_.FastForward(Seconds(10));
|
||||
service_thread_.Sync();
|
||||
|
||||
has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) { has_targets = true; });
|
||||
EXPECT_FALSE(has_targets);
|
||||
}
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargeDedupNoLossByEndpointId) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr int kShareTargetId2 = kShareTargetId + 100;
|
||||
constexpr absl::string_view kEndpointId = "endpoint_id";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
target.device_name = "device_name";
|
||||
ShareTarget target2 = target;
|
||||
target2.id = kShareTargetId2;
|
||||
target2.device_name = "device_name_2";
|
||||
ShareTarget merged_target = target;
|
||||
merged_target.device_name = "device_name_2";
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call)
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
}
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId, /*certificate=*/std::nullopt);
|
||||
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target2, kEndpointId, /*certificate=*/std::nullopt);
|
||||
|
||||
// Make sure share session is not created for new target id.
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId2),
|
||||
nullptr);
|
||||
// Make sure share session is created for original target id.
|
||||
OutgoingShareSession* session2 =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId);
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
}
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargeDedupNoLossByDeviceId) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr int kShareTargetId2 = kShareTargetId + 100;
|
||||
constexpr absl::string_view kEndpointId1 = "endpoint_id";
|
||||
constexpr absl::string_view kEndpointId2 = "endpoint_id_2";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
target.device_id = "device_id";
|
||||
target.device_name = "device_name";
|
||||
ShareTarget target2 = target;
|
||||
target2.id = kShareTargetId2;
|
||||
target2.device_name = "device_name_2";
|
||||
ShareTarget merged_target = target;
|
||||
merged_target.device_name = "device_name_2";
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call)
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
}
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId1, /*certificate=*/std::nullopt);
|
||||
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
|
||||
// Discover a new target with the same device id, but different endpoint id.
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target2, kEndpointId2, /*certificate=*/std::nullopt);
|
||||
|
||||
// Make sure share session is not created for new target id.
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId2),
|
||||
nullptr);
|
||||
// Make sure share session is created for original target id.
|
||||
OutgoingShareSession* session2 =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId2);
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
}
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargeDedupByEndpointId) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr int kShareTargetId2 = kShareTargetId + 100;
|
||||
constexpr absl::string_view kEndpointId = "endpoint_id";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
target.device_name = "device_name";
|
||||
ShareTarget disabled_target = target;
|
||||
disabled_target.receive_disabled = true;
|
||||
ShareTarget target2 = target;
|
||||
target2.id = kShareTargetId2;
|
||||
target2.device_name = "device_name_2";
|
||||
ShareTarget merged_target = target;
|
||||
merged_target.device_name = "device_name_2";
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call)
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, disabled_target);
|
||||
})
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
}
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId, /*certificate=*/std::nullopt);
|
||||
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
outgoing_targets_manager_.OnShareTargetLost(std::string(kEndpointId),
|
||||
Seconds(10));
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target2, kEndpointId, /*certificate=*/std::nullopt);
|
||||
|
||||
// Make sure share session is not created for new target id.
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId2),
|
||||
nullptr);
|
||||
// Make sure share session is created for original target id.
|
||||
OutgoingShareSession* session2 =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId);
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
|
||||
// Retention timer expired.
|
||||
clock_.FastForward(Seconds(10));
|
||||
service_thread_.Sync();
|
||||
|
||||
// Make sure share session is not removed after retention timer expired.
|
||||
session2 = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId);
|
||||
has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
}
|
||||
|
||||
TEST_F(OutgoingTargetsManagerTest, onShareTargeDedupByDeviceId) {
|
||||
constexpr int kShareTargetId = 1234;
|
||||
constexpr int kShareTargetId2 = kShareTargetId + 100;
|
||||
constexpr absl::string_view kEndpointId1 = "endpoint_id";
|
||||
constexpr absl::string_view kEndpointId2 = "endpoint_id_2";
|
||||
ShareTarget target;
|
||||
target.id = kShareTargetId;
|
||||
target.device_id = "device_id";
|
||||
target.device_name = "device_name";
|
||||
ShareTarget disabled_target = target;
|
||||
disabled_target.receive_disabled = true;
|
||||
ShareTarget target2 = target;
|
||||
target2.id = kShareTargetId2;
|
||||
target2.device_name = "device_name_2";
|
||||
ShareTarget merged_target = target;
|
||||
merged_target.device_name = "device_name_2";
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(share_target_discovered_callback_, Call).Times(1);
|
||||
EXPECT_CALL(share_target_updated_callback_, Call)
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, disabled_target);
|
||||
})
|
||||
.WillOnce([&](const ShareTarget& share_target) {
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
|
||||
EXPECT_CALL(transfer_update_callback_, Call).Times(0);
|
||||
}
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target, kEndpointId1, /*certificate=*/std::nullopt);
|
||||
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
|
||||
nullptr);
|
||||
outgoing_targets_manager_.OnShareTargetLost(std::string(kEndpointId1),
|
||||
Seconds(10));
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(1234), nullptr);
|
||||
|
||||
// Discover a new target with the same device id, but different endpoint id.
|
||||
outgoing_targets_manager_.OnShareTargetDiscovered(
|
||||
target2, kEndpointId2, /*certificate=*/std::nullopt);
|
||||
|
||||
// Make sure share session is not created for new target id.
|
||||
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId2),
|
||||
nullptr);
|
||||
// Make sure share session is created for original target id.
|
||||
OutgoingShareSession* session2 =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId2);
|
||||
bool has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
|
||||
// Retention timer expired.
|
||||
clock_.FastForward(Seconds(10));
|
||||
service_thread_.Sync();
|
||||
|
||||
// Make sure share session is not removed after retention timer expired.
|
||||
session2 = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
|
||||
EXPECT_NE(session2, nullptr);
|
||||
EXPECT_EQ(session2->share_target(), merged_target);
|
||||
EXPECT_EQ(session2->endpoint_id(), kEndpointId2);
|
||||
has_targets = false;
|
||||
outgoing_targets_manager_.ForEachShareTarget(
|
||||
[&](const ShareTarget& share_target) {
|
||||
has_targets = true;
|
||||
EXPECT_EQ(share_target, merged_target);
|
||||
});
|
||||
EXPECT_TRUE(has_targets);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby::sharing
|
||||
Reference in New Issue
Block a user