Merge remote-tracking branch 'nearby/main' into apply-upstream

# Conflicts:
#	MODULE.bazel
#	connections/implementation/mediums/ble_v2.cc
#	internal/platform/implementation/BUILD
This commit is contained in:
kidfromjupiter
2026-02-04 19:12:40 +00:00
1278 changed files with 930060 additions and 211365 deletions
+69 -9
View File
@@ -61,6 +61,8 @@ cc_library(
"//sharing/common:enum",
"//sharing/internal/base",
"//sharing/proto:wire_format_cc_proto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/random",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
@@ -113,7 +115,6 @@ cc_library(
"transfer_metadata.h",
"transfer_metadata_builder.h",
],
compatible_with = ["//buildenv/target:non_prod"],
visibility = [
"//location/nearby/apps/better_together/windows/nearby_share:__subpackages__",
"//location/nearby/cpp/sharing:__subpackages__",
@@ -220,6 +221,7 @@ cc_library(
":attachments",
":connection_types",
":incoming_frame_reader",
":nearby_sharing_util",
":paired_key_verification_runner",
":thread_timer",
":transfer_metadata",
@@ -269,16 +271,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",
@@ -287,6 +288,25 @@ cc_library(
],
)
cc_library(
name = "nearby_sharing_util",
srcs = ["nearby_sharing_util.cc"],
hdrs = ["nearby_sharing_util.h"],
deps = [
":types",
"//internal/base:file_path",
"//internal/platform:types",
"//proto:sharing_enums_cc_proto",
"//sharing/certificates",
"//sharing/common:enum",
"//sharing/internal/base",
"//sharing/internal/public:logging",
"@com_google_absl//absl/hash",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
],
)
cc_library(
name = "nearby_sharing_service",
srcs = [
@@ -300,7 +320,6 @@ cc_library(
"nearby_sharing_service_factory.cc",
"nearby_sharing_service_impl.cc",
"nearby_sharing_settings.cc",
"nearby_sharing_util.cc",
"service_observers.cc",
"service_observers.h",
"transfer_manager.cc",
@@ -319,7 +338,6 @@ cc_library(
"nearby_sharing_service_factory.h",
"nearby_sharing_service_impl.h",
"nearby_sharing_settings.h",
"nearby_sharing_util.h",
"payload_listener.h",
"share_target_discovered_callback.h",
"transfer_manager.h",
@@ -341,6 +359,7 @@ cc_library(
":incoming_frame_reader",
":nearby_connection_impl",
":nearby_sharing_decoder",
":nearby_sharing_util",
":outgoing_targets_manager",
":paired_key_verification_runner",
":share_session",
@@ -356,6 +375,7 @@ cc_library(
"//internal/flags:nearby_flags",
"//internal/network:url",
"//internal/platform:base",
"//internal/platform:logging",
"//internal/platform:mac_address",
"//internal/platform:types",
"//internal/platform/implementation:account_manager",
@@ -366,6 +386,7 @@ cc_library(
"//sharing/common",
"//sharing/common:enum",
"//sharing/contacts",
"//sharing/contacts:contacts_interface",
"//sharing/fast_initiation:nearby_fast_initiation",
"//sharing/flags/generated:generated_flags",
"//sharing/internal/api:platform",
@@ -384,7 +405,6 @@ cc_library(
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/hash",
"@com_google_absl//absl/meta:type_traits",
"@com_google_absl//absl/random",
"@com_google_absl//absl/status:statusor",
@@ -570,7 +590,7 @@ cc_test(
"//internal/test",
"//sharing/common:enum",
"//sharing/flags/generated:generated_flags",
"//sharing/internal/public:types",
"//sharing/internal/public:logging",
"//sharing/internal/test:nearby_test",
"//sharing/proto:enums_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
@@ -612,14 +632,12 @@ cc_test(
"//sharing/certificates:test_support",
"//sharing/common",
"//sharing/common:enum",
"//sharing/contacts",
"//sharing/contacts:test_support",
"//sharing/fast_initiation:nearby_fast_initiation",
"//sharing/fast_initiation:test_support",
"//sharing/flags/generated:generated_flags",
"//sharing/internal/api:mock_sharing_platform",
"//sharing/internal/api:platform",
"//sharing/internal/public:types",
"//sharing/internal/test:nearby_test",
"//sharing/local_device_data",
"//sharing/local_device_data:test_support",
@@ -720,6 +738,23 @@ cc_test(
],
)
cc_test(
name = "nearby_sharing_util_test",
srcs = ["nearby_sharing_util_test.cc"],
deps = [
":nearby_sharing_util",
"//internal/platform/implementation:platform_impl",
"//sharing/certificates",
"//sharing/proto:enums_cc_proto",
"//sharing/proto:share_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "payload_tracker_test",
srcs = ["payload_tracker_test.cc"],
@@ -855,6 +890,7 @@ cc_test(
":types",
"//internal/analytics:mock_event_logger",
"//internal/base:file_path",
"//internal/base:files",
"//internal/network:url",
"//internal/platform/implementation:platform_impl",
"//internal/test",
@@ -921,6 +957,8 @@ cc_test(
deps = [
":connection_types",
":nearby_sharing_service",
"//connections:core_types",
"//internal/platform:base",
"//internal/platform:types",
"//internal/platform/implementation:platform_impl",
"@com_github_protobuf_matchers//protobuf-matchers",
@@ -940,3 +978,25 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "outgoing_targets_manager_test",
srcs = ["outgoing_targets_manager_test.cc"],
deps = [
":attachments",
":connection_types",
":nearby_connection_impl",
":outgoing_targets_manager",
":share_session",
":test_support",
":transfer_metadata",
":types",
"//internal/base:file_path",
"//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",
],
)
+28 -28
View File
@@ -16,6 +16,7 @@
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
@@ -38,9 +39,7 @@
#include "sharing/share_target.h"
#include "sharing/text_attachment.h"
namespace nearby {
namespace sharing {
namespace analytics {
namespace nearby::sharing::analytics {
namespace {
using ::location::nearby::proto::sharing::EventCategory;
@@ -280,29 +279,32 @@ TEST_F(AnalyticsRecorderTest, NewDescribeAttachments) {
SharingLog::FileAttachment::DOCUMENT);
});
AttachmentContainer attachments(
{TextAttachment(5, service::proto::TextMetadata::TEXT,
std::string(kTextBody), kTextBody.size()),
TextAttachment(6, service::proto::TextMetadata::PHONE_NUMBER,
std::string(kTextBody), kTextBody.size()),
TextAttachment(7, service::proto::TextMetadata::URL,
std::string(kTextBody), kTextBody.size()),
TextAttachment(8, service::proto::TextMetadata::ADDRESS,
std::string(kTextBody), kTextBody.size()),
TextAttachment(9, service::proto::TextMetadata::UNKNOWN,
std::string(kTextBody), kTextBody.size())},
{FileAttachment(1, 2, std::string(kFileName), "",
service::proto::FileMetadata::IMAGE),
FileAttachment(2, 3, std::string(kFileDocumentName),
std::string(kFileMimeType),
service::proto::FileMetadata::DOCUMENT),
FileAttachment(3, 4, std::string(kFileName), "",
service::proto::FileMetadata::AUDIO),
FileAttachment(4, 5, std::string(kFileName), std::string(kTextMimeType),
service::proto::FileMetadata::DOCUMENT)},
{});
std::unique_ptr<AttachmentContainer> attachments =
AttachmentContainer::Builder(
{TextAttachment(5, service::proto::TextMetadata::TEXT,
std::string(kTextBody), kTextBody.size()),
TextAttachment(6, service::proto::TextMetadata::PHONE_NUMBER,
std::string(kTextBody), kTextBody.size()),
TextAttachment(7, service::proto::TextMetadata::URL,
std::string(kTextBody), kTextBody.size()),
TextAttachment(8, service::proto::TextMetadata::ADDRESS,
std::string(kTextBody), kTextBody.size()),
TextAttachment(9, service::proto::TextMetadata::UNKNOWN,
std::string(kTextBody), kTextBody.size())},
{FileAttachment(1, 2, std::string(kFileName), "",
service::proto::FileMetadata::IMAGE),
FileAttachment(2, 3, std::string(kFileDocumentName),
std::string(kFileMimeType),
service::proto::FileMetadata::DOCUMENT),
FileAttachment(3, 4, std::string(kFileName), "",
service::proto::FileMetadata::AUDIO),
FileAttachment(4, 5, std::string(kFileName),
std::string(kTextMimeType),
service::proto::FileMetadata::DOCUMENT)},
{})
.Build();
analytics_recoder().NewDescribeAttachments(attachments);
analytics_recoder().NewDescribeAttachments(*attachments);
}
TEST_F(AnalyticsRecorderTest, EmptyDescribeAttachments) {
@@ -896,6 +898,4 @@ TEST_F(AnalyticsRecorderTest, GenerateID) {
}
} // namespace
} // namespace analytics
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing::analytics
+5 -22
View File
@@ -20,8 +20,7 @@
#include "absl/random/random.h"
#include "proto/sharing_enums.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
namespace {
using ::location::nearby::proto::sharing::AttachmentSourceType;
@@ -33,32 +32,16 @@ int64_t CreateRandomId() {
} // namespace
// TODO(b/258690183): Add unit tests for Attachment with same and different ids
Attachment::Attachment(Attachment::Family family, int64_t size,
int32_t batch_id, AttachmentSourceType source_type)
: id_(CreateRandomId()),
family_(family),
size_(size),
batch_id_(batch_id),
source_type_(source_type) {}
: Attachment(/*id=*/0, family, size, batch_id, source_type) {}
Attachment::Attachment(int64_t id, Attachment::Family family, int64_t size,
int32_t batch_id, AttachmentSourceType source_type)
: id_(id == 0 ? CreateRandomId() : id),
family_(family),
size_(size),
batch_id_(batch_id),
source_type_(source_type) {}
source_type_(source_type),
size_(size) {}
Attachment::Attachment(const Attachment&) = default;
Attachment::Attachment(Attachment&&) = default;
Attachment& Attachment::operator=(const Attachment&) = default;
Attachment& Attachment::operator=(Attachment&&) = default;
Attachment::~Attachment() = default;
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
+7 -13
View File
@@ -21,8 +21,7 @@
#include "proto/sharing_enums.pb.h"
#include "sharing/common/nearby_share_enums.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
// A single attachment to be sent by / received from a ShareTarget, can be
// either a file or text.
@@ -41,11 +40,7 @@ class Attachment {
Attachment(
int64_t id, Family family, int64_t size, int32_t batch_id,
location::nearby::proto::sharing::AttachmentSourceType source_type);
Attachment(const Attachment&);
Attachment(Attachment&&);
Attachment& operator=(const Attachment&);
Attachment& operator=(Attachment&&);
virtual ~Attachment();
virtual ~Attachment() = default;
int64_t id() const { return id_; }
Family family() const { return family_; }
@@ -60,14 +55,13 @@ class Attachment {
virtual ShareType GetShareType() const = 0;
private:
int64_t id_;
Family family_;
const int64_t id_;
const Family family_;
const int32_t batch_id_;
const location::nearby::proto::sharing::AttachmentSourceType source_type_;
int64_t size_;
int32_t batch_id_;
location::nearby::proto::sharing::AttachmentSourceType source_type_;
};
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
#endif // THIRD_PARTY_NEARBY_SHARING_ATTACHMENT_H_
+69 -5
View File
@@ -14,23 +14,81 @@
#include "sharing/attachment_container.h"
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
#include "sharing/file_attachment.h"
#include "sharing/text_attachment.h"
#include "sharing/wifi_credentials_attachment.h"
namespace nearby::sharing {
AttachmentContainer::Builder&
AttachmentContainer::Builder::ReserveAttachmentsCount(
int text_attachments_count, int file_attachments_count,
int wifi_credentials_attachments_count) {
text_attachments_.reserve(text_attachments_count);
file_attachments_.reserve(file_attachments_count);
wifi_credentials_attachments_.reserve(wifi_credentials_attachments_count);
return *this;
}
AttachmentContainer::Builder& AttachmentContainer::Builder::AddTextAttachment(
TextAttachment text_attachment) {
text_attachments_.push_back(std::move(text_attachment));
return *this;
}
AttachmentContainer::Builder& AttachmentContainer::Builder::AddFileAttachment(
FileAttachment file_attachment) {
file_attachments_.push_back(std::move(file_attachment));
return *this;
}
AttachmentContainer::Builder&
AttachmentContainer::Builder::AddWifiCredentialsAttachment(
WifiCredentialsAttachment wifi_credentials_attachment) {
wifi_credentials_attachments_.push_back(
std::move(wifi_credentials_attachment));
return *this;
}
std::unique_ptr<AttachmentContainer> AttachmentContainer::Builder::Build() {
return absl::WrapUnique(new AttachmentContainer(
std::move(text_attachments_), std::move(file_attachments_),
std::move(wifi_credentials_attachments_)));
}
AttachmentContainer::AttachmentContainer(
std::vector<TextAttachment> text_attachments,
std::vector<FileAttachment> file_attachments,
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments)
: text_attachments_(std::move(text_attachments)),
file_attachments_(std::move(file_attachments)),
wifi_credentials_attachments_(std::move(wifi_credentials_attachments)) {}
wifi_credentials_attachments_(std::move(wifi_credentials_attachments)) {
BuildIndex();
}
AttachmentContainer::AttachmentContainer(AttachmentContainer&& other) {
text_attachments_ = std::move(other.text_attachments_);
file_attachments_ = std::move(other.file_attachments_);
wifi_credentials_attachments_ =
std::move(other.wifi_credentials_attachments_);
BuildIndex();
}
AttachmentContainer& AttachmentContainer::operator=(
AttachmentContainer&& other) {
text_attachments_ = std::move(other.text_attachments_);
file_attachments_ = std::move(other.file_attachments_);
wifi_credentials_attachments_ =
std::move(other.wifi_credentials_attachments_);
BuildIndex();
return *this;
}
int64_t AttachmentContainer::GetTotalAttachmentsSize() const {
int64_t size_in_bytes = 0;
@@ -77,10 +135,16 @@ void AttachmentContainer::ClearAttachments() {
}
}
void AttachmentContainer::Clear() {
file_attachments_.clear();
text_attachments_.clear();
wifi_credentials_attachments_.clear();
void AttachmentContainer::BuildIndex() {
for (const auto& text : text_attachments_) {
attachment_id_map_[text.id()] = &text;
}
for (const auto& file : file_attachments_) {
attachment_id_map_[file.id()] = &file;
}
for (const auto& wifi_credentials : wifi_credentials_attachments_) {
attachment_id_map_[wifi_credentials.id()] = &wifi_credentials;
}
}
} // namespace nearby::sharing
+52 -23
View File
@@ -16,8 +16,11 @@
#define THIRD_PARTY_NEARBY_SHARING_ATTACHMENT_CONTAINER_H_
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "sharing/attachment.h"
#include "sharing/file_attachment.h"
#include "sharing/text_attachment.h"
#include "sharing/wifi_credentials_attachment.h"
@@ -28,15 +31,40 @@ namespace nearby::sharing {
// This class is thread-compatible (go/thread-compatible).
class AttachmentContainer {
public:
AttachmentContainer(
std::vector<TextAttachment> text_attachments,
std::vector<FileAttachment> file_attachments,
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments);
class Builder {
public:
Builder() = default;
Builder(std::vector<TextAttachment> text_attachments,
std::vector<FileAttachment> file_attachments,
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments)
: text_attachments_(std::move(text_attachments)),
file_attachments_(std::move(file_attachments)),
wifi_credentials_attachments_(
std::move(wifi_credentials_attachments)) {}
Builder& ReserveAttachmentsCount(int text_attachments_count,
int file_attachments_count,
int wifi_credentials_attachments_count);
Builder& AddTextAttachment(TextAttachment text_attachment);
Builder& AddFileAttachment(FileAttachment file_attachment);
Builder& AddWifiCredentialsAttachment(
WifiCredentialsAttachment wifi_credentials_attachment);
bool Empty() const {
return text_attachments_.empty() && file_attachments_.empty() &&
wifi_credentials_attachments_.empty();
}
std::unique_ptr<AttachmentContainer> Build();
private:
std::vector<TextAttachment> text_attachments_;
std::vector<FileAttachment> file_attachments_;
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments_;
};
AttachmentContainer() = default;
AttachmentContainer(const AttachmentContainer&) = default;
AttachmentContainer(AttachmentContainer&&) = default;
AttachmentContainer& operator=(const AttachmentContainer&) = default;
AttachmentContainer& operator=(AttachmentContainer&&) = default;
AttachmentContainer(AttachmentContainer&&);
AttachmentContainer& operator=(AttachmentContainer&&);
~AttachmentContainer() = default;
const std::vector<TextAttachment>& GetTextAttachments() const {
@@ -50,18 +78,6 @@ class AttachmentContainer {
return wifi_credentials_attachments_;
}
void AddTextAttachment(TextAttachment text_attachment) {
text_attachments_.push_back(std::move(text_attachment));
}
void AddFileAttachment(FileAttachment file_attachment) {
file_attachments_.push_back(std::move(file_attachment));
}
void AddWifiCredentialsAttachment(
WifiCredentialsAttachment wifi_credentials_attachment) {
wifi_credentials_attachments_.push_back(
std::move(wifi_credentials_attachment));
}
TextAttachment& GetMutableTextAttachment(int index) {
return text_attachments_[index];
}
@@ -74,6 +90,14 @@ class AttachmentContainer {
return wifi_credentials_attachments_[index];
}
const Attachment* GetAttachment(int64_t id) const {
const auto it = attachment_id_map_.find(id);
if (it == attachment_id_map_.end()) {
return nullptr;
}
return it->second;
}
// Returns the total number of attachments of all types.
int GetAttachmentCount() const {
return text_attachments_.size() + file_attachments_.size() +
@@ -96,13 +120,18 @@ class AttachmentContainer {
// place.
void ClearAttachments();
// Delete all attachments.
void Clear();
private:
AttachmentContainer(
std::vector<TextAttachment> text_attachments,
std::vector<FileAttachment> file_attachments,
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments);
// Build id to attachment index.
void BuildIndex();
std::vector<TextAttachment> text_attachments_;
std::vector<FileAttachment> file_attachments_;
std::vector<WifiCredentialsAttachment> wifi_credentials_attachments_;
absl::flat_hash_map<int64_t, const Attachment*> attachment_id_map_;
};
} // namespace nearby::sharing
+83 -72
View File
@@ -15,6 +15,7 @@
#include "sharing/attachment_container.h"
#include <cstdint>
#include <memory>
#include <optional>
#include <vector>
@@ -72,132 +73,142 @@ class AttachmentContainerTest : public ::testing::Test {
};
TEST_F(AttachmentContainerTest, Constructor) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.AddFileAttachment(file1_)
.AddWifiCredentialsAttachment(wifi1_)
.Build();
EXPECT_THAT(container.GetTextAttachments(),
EXPECT_THAT(container->GetTextAttachments(),
UnorderedElementsAre(text1_, text2_));
EXPECT_THAT(container.GetFileAttachments(), UnorderedElementsAre(file1_));
EXPECT_THAT(container.GetWifiCredentialsAttachments(),
EXPECT_THAT(container->GetFileAttachments(), UnorderedElementsAre(file1_));
EXPECT_THAT(container->GetWifiCredentialsAttachments(),
UnorderedElementsAre(wifi1_));
}
TEST_F(AttachmentContainerTest, AddTextAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.Build();
container.AddTextAttachment(text1_);
container.AddTextAttachment(text2_);
EXPECT_THAT(container.GetTextAttachments(),
EXPECT_THAT(container->GetTextAttachments(),
UnorderedElementsAre(text1_, text2_));
}
TEST_F(AttachmentContainerTest, AddFileAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder().AddFileAttachment(file1_).Build();
container.AddFileAttachment(file1_);
EXPECT_THAT(container.GetFileAttachments(), UnorderedElementsAre(file1_));
EXPECT_THAT(container->GetFileAttachments(), UnorderedElementsAre(file1_));
}
TEST_F(AttachmentContainerTest, AddWifiCredentialsAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddWifiCredentialsAttachment(wifi1_)
.Build();
container.AddWifiCredentialsAttachment(wifi1_);
EXPECT_THAT(container.GetWifiCredentialsAttachments(),
EXPECT_THAT(container->GetWifiCredentialsAttachments(),
UnorderedElementsAre(wifi1_));
}
TEST_F(AttachmentContainerTest, GetMutableTextAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.Build();
container.AddTextAttachment(text1_);
container.AddTextAttachment(text2_);
EXPECT_THAT(container.GetMutableTextAttachment(0), Eq(text1_));
EXPECT_THAT(container.GetMutableTextAttachment(1), Eq(text2_));
EXPECT_THAT(container->GetMutableTextAttachment(0), Eq(text1_));
EXPECT_THAT(container->GetMutableTextAttachment(1), Eq(text2_));
}
TEST_F(AttachmentContainerTest, GetMutableFileAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder().AddFileAttachment(file1_).Build();
container.AddFileAttachment(file1_);
EXPECT_THAT(container.GetMutableFileAttachment(0), Eq(file1_));
EXPECT_THAT(container->GetMutableFileAttachment(0), Eq(file1_));
}
TEST_F(AttachmentContainerTest, GetMutableWifiCredentialsAttachment) {
AttachmentContainer container;
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddWifiCredentialsAttachment(wifi1_)
.Build();
container.AddWifiCredentialsAttachment(wifi1_);
EXPECT_THAT(container.GetMutableWifiCredentialsAttachment(0), Eq(wifi1_));
EXPECT_THAT(container->GetMutableWifiCredentialsAttachment(0), Eq(wifi1_));
}
TEST_F(AttachmentContainerTest, AttachmentCount) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.AddFileAttachment(file1_)
.AddWifiCredentialsAttachment(wifi1_)
.Build();
EXPECT_THAT(container.GetAttachmentCount(), Eq(4));
EXPECT_THAT(container->GetAttachmentCount(), Eq(4));
}
TEST_F(AttachmentContainerTest, GetTotalAttachmentsSize) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{});
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.AddFileAttachment(file1_)
.Build();
EXPECT_THAT(container.GetTotalAttachmentsSize(), Eq(18 + 20 + 100000));
EXPECT_THAT(container->GetTotalAttachmentsSize(), Eq(18 + 20 + 100000));
}
TEST_F(AttachmentContainerTest, HasAttachments) {
AttachmentContainer container;
AttachmentContainer::Builder builder = AttachmentContainer::Builder();
EXPECT_THAT(container.HasAttachments(), IsFalse());
EXPECT_THAT(builder.Empty(), IsTrue());
container.AddWifiCredentialsAttachment(wifi1_);
builder.AddWifiCredentialsAttachment(wifi1_);
EXPECT_THAT(container.HasAttachments(), IsTrue());
EXPECT_THAT(builder.Empty(), IsFalse());
}
TEST_F(AttachmentContainerTest, ClearAttachments) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.AddFileAttachment(file1_)
.AddWifiCredentialsAttachment(wifi1_)
.Build();
container.ClearAttachments();
container->ClearAttachments();
ASSERT_THAT(container.GetTextAttachments(), SizeIs(2));
EXPECT_THAT(container.GetTextAttachments()[0].text_body(), IsEmpty());
EXPECT_THAT(container.GetTextAttachments()[1].text_body(), IsEmpty());
ASSERT_THAT(container.GetFileAttachments(), SizeIs(1));
EXPECT_THAT(container.GetFileAttachments()[0].file_path(), Eq(std::nullopt));
ASSERT_THAT(container.GetWifiCredentialsAttachments(), SizeIs(1));
EXPECT_THAT(container.GetWifiCredentialsAttachments()[0].password(),
ASSERT_THAT(container->GetTextAttachments(), SizeIs(2));
EXPECT_THAT(container->GetTextAttachments()[0].text_body(), IsEmpty());
EXPECT_THAT(container->GetTextAttachments()[1].text_body(), IsEmpty());
ASSERT_THAT(container->GetFileAttachments(), SizeIs(1));
EXPECT_THAT(container->GetFileAttachments()[0].file_path(), Eq(std::nullopt));
ASSERT_THAT(container->GetWifiCredentialsAttachments(), SizeIs(1));
EXPECT_THAT(container->GetWifiCredentialsAttachments()[0].password(),
IsEmpty());
EXPECT_THAT(container.GetWifiCredentialsAttachments()[0].is_hidden(),
EXPECT_THAT(container->GetWifiCredentialsAttachments()[0].is_hidden(),
IsFalse());
}
TEST_F(AttachmentContainerTest, Clear) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
EXPECT_THAT(container.HasAttachments(), IsTrue());
container.Clear();
EXPECT_THAT(container.HasAttachments(), IsFalse());
}
TEST_F(AttachmentContainerTest, GetStorageSize) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
std::unique_ptr<AttachmentContainer> container =
AttachmentContainer::Builder()
.AddTextAttachment(text1_)
.AddTextAttachment(text2_)
.AddFileAttachment(file1_)
.AddWifiCredentialsAttachment(wifi1_)
.Build();
int64_t storage_size = container.GetStorageSize();
int64_t storage_size = container->GetStorageSize();
EXPECT_THAT(storage_size, Eq(file1_.size()));
}
+1 -2
View File
@@ -124,13 +124,12 @@ cc_test(
":test_support",
"//internal/platform:mac_address",
"//internal/platform/implementation:account_manager",
"//internal/platform/implementation:platform_impl", # fixdeps: keep
"//internal/platform/implementation:platform_impl",
"//internal/test",
"//proto/identity/v1:resources_cc_proto",
"//proto/identity/v1:rpcs_cc_proto",
"//sharing/common",
"//sharing/common:enum",
"//sharing/contacts:test_support",
"//sharing/internal/api:mock_sharing_platform",
"//sharing/internal/api:platform",
"//sharing/internal/public:pref_names",
@@ -48,7 +48,6 @@
#include "sharing/certificates/nearby_share_encrypted_metadata_key.h"
#include "sharing/certificates/nearby_share_private_certificate.h"
#include "sharing/certificates/test_util.h"
#include "sharing/contacts/fake_nearby_share_contact_manager.h"
#include "sharing/internal/api/fake_nearby_share_client.h"
#include "sharing/internal/api/mock_sharing_platform.h"
#include "sharing/internal/public/pref_names.h"
@@ -114,7 +113,6 @@ class NearbyShareCertificateManagerImplTest
local_device_data_manager_ =
std::make_unique<FakeNearbyShareLocalDeviceDataManager>(
kDefaultDeviceName);
contact_manager_ = std::make_unique<FakeNearbyShareContactManager>();
AccountManager::Account account{
.display_name = GetNearbyShareTestMetadata().full_name(),
@@ -501,7 +499,6 @@ class NearbyShareCertificateManagerImplTest
FakeNearbyShareCertificateStorage::Factory cert_store_factory_;
std::unique_ptr<FakeNearbyShareLocalDeviceDataManager>
local_device_data_manager_;
std::unique_ptr<FakeNearbyShareContactManager> contact_manager_;
std::unique_ptr<NearbyShareCertificateManager> cert_manager_;
};
+15 -35
View File
@@ -17,60 +17,49 @@ load("@rules_cc//cc:cc_test.bzl", "cc_test")
licenses(["notice"])
cc_library(
name = "contacts_interface",
hdrs = [
"nearby_share_contact_manager.h",
],
visibility = ["//visibility:public"],
deps = [
"//sharing/proto:share_cc_proto",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/status:statusor",
],
)
cc_library(
name = "contacts",
srcs = [
"nearby_share_contact_manager.cc",
"nearby_share_contact_manager_impl.cc",
],
hdrs = [
"nearby_share_contact_manager.h",
"nearby_share_contact_manager_impl.h",
],
visibility = ["//visibility:public"],
deps = [
"//internal/base",
"//internal/crypto_cros",
"//internal/flags:nearby_flags",
":contacts_interface",
"//internal/platform:types",
"//internal/platform/implementation:account_manager",
"//sharing/common",
"//sharing/flags/generated:generated_flags",
"//sharing/internal/api:platform",
"//sharing/internal/base",
"//sharing/internal/public:logging",
"//sharing/internal/public:types",
"//sharing/local_device_data",
"//sharing/proto:share_cc_proto",
"//sharing/scheduling",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
],
)
cc_library(
name = "test_support",
testonly = True,
srcs = [
"fake_nearby_share_contact_manager.cc",
],
hdrs = [
"fake_nearby_share_contact_manager.h",
],
visibility = ["//visibility:public"],
deps = [
":contacts",
"//internal/platform/implementation:account_manager",
"//internal/platform/implementation:types",
"//sharing/internal/api:platform",
"//sharing/internal/public:types",
"//sharing/local_device_data",
],
deps = [":contacts_interface"],
)
cc_test(
@@ -83,20 +72,11 @@ cc_test(
"//internal/platform/implementation:account_manager",
"//internal/platform/implementation:platform_impl",
"//internal/test",
"//sharing/common",
"//sharing/internal/api:mock_sharing_platform",
"//sharing/internal/api:platform",
"//sharing/internal/test:nearby_test",
"//sharing/local_device_data:test_support",
"//sharing/proto:share_cc_proto",
"//sharing/scheduling",
"//sharing/scheduling:test_support",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
],
@@ -1,52 +0,0 @@
// Copyright 2021-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sharing/contacts/fake_nearby_share_contact_manager.h"
#include <memory>
#include <vector>
#include "internal/platform/implementation/account_manager.h"
#include "sharing/contacts/nearby_share_contact_manager.h"
#include "sharing/internal/api/sharing_rpc_client.h"
#include "sharing/internal/public/context.h"
namespace nearby {
namespace sharing {
FakeNearbyShareContactManager::Factory::Factory() = default;
FakeNearbyShareContactManager::Factory::~Factory() = default;
std::unique_ptr<NearbyShareContactManager>
FakeNearbyShareContactManager::Factory::CreateInstance(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory) {
latest_nearby_client_factory_ = nearby_client_factory;
latest_account_manager_ = &account_manager;
auto instance = std::make_unique<FakeNearbyShareContactManager>();
instances_.push_back(instance.get());
return instance;
}
FakeNearbyShareContactManager::FakeNearbyShareContactManager() = default;
FakeNearbyShareContactManager::~FakeNearbyShareContactManager() = default;
void FakeNearbyShareContactManager::GetContacts(ContactsCallback callback) {}
} // namespace sharing
} // namespace nearby
@@ -15,68 +15,19 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_CONTACTS_FAKE_NEARBY_SHARE_CONTACT_MANAGER_H_
#define THIRD_PARTY_NEARBY_SHARING_CONTACTS_FAKE_NEARBY_SHARE_CONTACT_MANAGER_H_
#include <stddef.h>
#include <memory>
#include <vector>
#include "internal/platform/implementation/account_manager.h"
#include "sharing/contacts/nearby_share_contact_manager.h"
#include "sharing/contacts/nearby_share_contact_manager_impl.h"
#include "sharing/internal/api/sharing_rpc_client.h"
#include "sharing/internal/public/context.h"
namespace nearby {
namespace sharing {
// A fake implementation of NearbyShareContactManager, along with a fake
// factory, to be used in tests. Stores parameters input into
// NearbyShareContactManager method calls. Use the notification methods from the
// base class--NotifyContactsDownloaded() and NotifyContactsUploaded()--to alert
// observers of changes; these methods are made public in this fake class.
// A fake implementation of NearbyShareContactManager.
class FakeNearbyShareContactManager : public NearbyShareContactManager {
public:
// Factory that creates FakeNearbyShareContactManager instances. Use in
// NearbyShareContactManagerImpl::Factor::SetFactoryForTesting() in unit
// tests.
class Factory : public NearbyShareContactManagerImpl::Factory {
public:
Factory();
~Factory() override;
// Returns all FakeNearbyShareContactManager instances created by
// CreateInstance().
std::vector<FakeNearbyShareContactManager*>& instances() {
return instances_;
}
nearby::sharing::api::SharingRpcClientFactory* latest_http_client_factory()
const {
return latest_nearby_client_factory_;
}
AccountManager* latest_account_manager() const {
return latest_account_manager_;
}
private:
// NearbyShareContactManagerImpl::Factory:
std::unique_ptr<NearbyShareContactManager> CreateInstance(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory)
override;
std::vector<FakeNearbyShareContactManager*> instances_;
nearby::sharing::api::SharingRpcClientFactory*
latest_nearby_client_factory_ = nullptr;
AccountManager* latest_account_manager_ = nullptr;
};
FakeNearbyShareContactManager();
~FakeNearbyShareContactManager() override;
FakeNearbyShareContactManager() = default;
~FakeNearbyShareContactManager() override = default;
private:
void GetContacts(ContactsCallback callback) override;
void GetContacts(ContactsCallback callback) override {};
};
} // namespace sharing
@@ -1,29 +0,0 @@
// Copyright 2021-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sharing/contacts/nearby_share_contact_manager.h"
#include <stdint.h>
#include "sharing/proto/rpc_resources.pb.h"
namespace nearby {
namespace sharing {
NearbyShareContactManager::NearbyShareContactManager() = default;
NearbyShareContactManager::~NearbyShareContactManager() = default;
} // namespace sharing
} // namespace nearby
@@ -26,27 +26,15 @@
namespace nearby {
namespace sharing {
// The Nearby Share contacts manager interfaces with the Nearby server in the
// following ways:
// 1) The user's contacts are downloaded from People API, using the Nearby
// server as a proxy.
// 2) All the user's contacts are uploaded to Nearby server, along with an
// indication of what contacts are allowed for selected-contacts visibility
// mode. The Nearby server will distribute all-contacts visibility
// certificates accordingly. For privacy reasons, the Nearby server needs to
// explicitly receive the list of contacts from the device instead of pulling
// them directly from People API.
//
// All contact data and update notifications are conveyed via observer methods;
// the manager does not return data directly from function calls.
// The Nearby Share contacts manager retrieves the user's contact list from the
// server.
class NearbyShareContactManager {
public:
using ContactsCallback = absl::AnyInvocable<
void(absl::StatusOr<std::vector<nearby::sharing::proto::ContactRecord>>,
uint32_t num_unreachable_contacts_filtered_out) &&>;
NearbyShareContactManager();
virtual ~NearbyShareContactManager();
virtual ~NearbyShareContactManager() = default;
// Retrieves the user's contact list from the server.
virtual void GetContacts(ContactsCallback callback) = 0;
@@ -23,7 +23,6 @@
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/notification.h"
#include "internal/platform/implementation/account_manager.h"
@@ -42,53 +41,32 @@ using ::nearby::sharing::proto::ContactRecord;
using ::nearby::sharing::proto::ListContactPeopleRequest;
using ::nearby::sharing::proto::ListContactPeopleResponse;
void FilterOutUnreachableContacts(std::vector<ContactRecord>& contacts) {
contacts.erase(
std::remove_if(contacts.begin(), contacts.end(),
[](const nearby::sharing::proto::ContactRecord& contact) {
return !contact.is_reachable();
}),
contacts.end());
}
// Class for maintaining a single instance of contacts download request. It
// is responsible for downloading all available pages and making the results
// or error available.
class ContactDownloadContext {
public:
ContactDownloadContext(
nearby::sharing::api::SharingRpcClient* nearby_share_client,
NearbyShareContactManager::ContactsCallback download_callback)
: nearby_share_client_(nearby_share_client),
download_callback_(std::move(download_callback)) {}
} // namespace
// Fetches the next page of contacts.
// If |next_page_token_| is empty, it fetches the first page.
// On successful download, if page token in the response is empty, the
// |download_callback_| is invoked with all downloaded contacts.
void FetchNextPage();
// static
NearbyShareContactManagerImpl::Factory*
NearbyShareContactManagerImpl::Factory::test_factory_ = nullptr;
private:
nearby::sharing::api::SharingRpcClient* const nearby_share_client_;
std::optional<std::string> next_page_token_;
int page_number_ = 1;
std::vector<ContactRecord> contacts_;
NearbyShareContactManager::ContactsCallback download_callback_;
};
// static
std::unique_ptr<NearbyShareContactManager>
NearbyShareContactManagerImpl::Factory::Create(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory) {
if (test_factory_) {
return test_factory_->CreateInstance(context, account_manager,
nearby_client_factory);
}
return absl::WrapUnique(new NearbyShareContactManagerImpl(
context, account_manager, nearby_client_factory));
}
// static
void NearbyShareContactManagerImpl::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
NearbyShareContactManagerImpl::Factory::~Factory() = default;
NearbyShareContactManagerImpl::NearbyShareContactManagerImpl(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory)
: account_manager_(account_manager),
nearby_share_client_(nearby_client_factory->CreateInstance()),
executor_(context->CreateSequencedTaskRunner()) {}
NearbyShareContactManagerImpl::~NearbyShareContactManagerImpl() = default;
void NearbyShareContactManagerImpl::ContactDownloadContext::FetchNextPage() {
void ContactDownloadContext::FetchNextPage() {
LOG(INFO) << "Downloading contacts page=" << page_number_++;
ListContactPeopleRequest request;
if (next_page_token_.has_value()) {
@@ -112,7 +90,12 @@ void NearbyShareContactManagerImpl::ContactDownloadContext::FetchNextPage() {
// We should filter here because we only care about contacts that we
// can share with.
uint32_t contacts_size = contacts_.size();
FilterOutUnreachableContacts(contacts_);
// Filter out unreachable contacts.
contacts_.erase(std::remove_if(contacts_.begin(), contacts_.end(),
[](const ContactRecord& contact) {
return !contact.is_reachable();
}),
contacts_.end());
uint32_t num_unreachable_contacts_filtered_out =
contacts_size - contacts_.size();
std::move(download_callback_)(std::move(contacts_),
@@ -125,6 +108,15 @@ void NearbyShareContactManagerImpl::ContactDownloadContext::FetchNextPage() {
});
}
} // namespace
NearbyShareContactManagerImpl::NearbyShareContactManagerImpl(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory)
: account_manager_(account_manager),
nearby_share_client_(nearby_client_factory->CreateInstance()),
executor_(context->CreateSequencedTaskRunner()) {}
void NearbyShareContactManagerImpl::GetContacts(ContactsCallback callback) {
executor_->PostTask([this, callback = std::move(callback)]() mutable {
LOG(INFO) << "Start downloading contacts";
@@ -15,94 +15,26 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_CONTACTS_NEARBY_SHARE_CONTACT_MANAGER_IMPL_H_
#define THIRD_PARTY_NEARBY_SHARING_CONTACTS_NEARBY_SHARE_CONTACT_MANAGER_IMPL_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "internal/platform/implementation/account_manager.h"
#include "internal/platform/task_runner.h"
#include "sharing/contacts/nearby_share_contact_manager.h"
#include "sharing/internal/api/sharing_rpc_client.h"
#include "sharing/internal/public/context.h"
#include "sharing/proto/rpc_resources.pb.h"
namespace nearby {
namespace sharing {
// Implementation of NearbyShareContactManager that persists the set of allowed
// contact IDs--for selected-contacts visibility mode--in prefs. Other
// contact data is downloaded from People API, via the NearbyShare server, as
// needed.
//
// The Nearby Share server must be explicitly informed of all contacts this
// device is aware of--needed for all-contacts visibility mode--as well as what
// contacts are allowed for selected-contacts visibility mode. These uploaded
// contact lists are used by the server to distribute the device's public
// certificates accordingly. This implementation persists a hash of the last
// uploaded contact data, and after every contacts download, a subsequent upload
// request is made if we detect that the contact list or allowlist has changed
// since the last successful upload. We also schedule periodic contact uploads
// just in case the server removed the record.
//
// In addition to supporting on-demand contact downloads, this implementation
// periodically checks in with the Nearby Share server to see if the user's
// contact list has changed since the last upload.
class NearbyShareContactManagerImpl : public NearbyShareContactManager {
public:
class Factory {
public:
static std::unique_ptr<NearbyShareContactManager> Create(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory);
static void SetFactoryForTesting(Factory* test_factory);
protected:
virtual ~Factory();
virtual std::unique_ptr<NearbyShareContactManager> CreateInstance(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory*
nearby_client_factory) = 0;
private:
static Factory* test_factory_;
};
~NearbyShareContactManagerImpl() override;
private:
// Class for maintaining a single instance of contacts download request. It
// is responsible for downloading all available pages and making the results
// or error available.
class ContactDownloadContext {
public:
ContactDownloadContext(
nearby::sharing::api::SharingRpcClient* nearby_share_client,
ContactsCallback download_callback)
: nearby_share_client_(nearby_share_client),
download_callback_(std::move(download_callback)) {}
// Fetches the next page of contacts.
// If |next_page_token_| is empty, it fetches the first page.
// On successful download, if page token in the response is empty, the
// |download_callback_| is invoked with all downloaded contacts.
void FetchNextPage();
private:
nearby::sharing::api::SharingRpcClient* const nearby_share_client_;
std::optional<std::string> next_page_token_;
int page_number_ = 1;
std::vector<nearby::sharing::proto::ContactRecord> contacts_;
ContactsCallback download_callback_;
};
NearbyShareContactManagerImpl(
Context* context, AccountManager& account_manager,
nearby::sharing::api::SharingRpcClientFactory* nearby_client_factory);
~NearbyShareContactManagerImpl() override = default;
private:
// NearbyShareContactsManager:
void GetContacts(ContactsCallback callback) override;
@@ -26,14 +26,11 @@
#include "absl/time/time.h"
#include "internal/platform/implementation/account_manager.h"
#include "internal/test/fake_account_manager.h"
#include "sharing/contacts/nearby_share_contact_manager.h"
#include "sharing/internal/api/fake_nearby_share_client.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/local_device_data/fake_nearby_share_local_device_data_manager.h"
#include "sharing/proto/contact_rpc.pb.h"
#include "sharing/proto/rpc_resources.pb.h"
#include "sharing/scheduling/fake_nearby_share_scheduler_factory.h"
#include "sharing/scheduling/nearby_share_scheduler_factory.h"
namespace nearby::sharing {
namespace {
@@ -61,19 +58,17 @@ class NearbyShareContactManagerImplTest
~NearbyShareContactManagerImplTest() override = default;
void SetUp() override {
NearbyShareSchedulerFactory::SetFactoryForTesting(&scheduler_factory_);
AccountManager::Account account;
account.id = kTestAccountId;
account.email = kTestProfileUserName;
fake_account_manager_.SetAccount(account);
manager_ = NearbyShareContactManagerImpl::Factory::Create(
manager_ = std::make_unique<NearbyShareContactManagerImpl>(
&fake_context_, fake_account_manager_, &nearby_client_factory_);
}
void TearDown() override {
manager_.reset();
NearbyShareSchedulerFactory::SetFactoryForTesting(nullptr);
}
void Sync() {
@@ -101,8 +96,7 @@ class NearbyShareContactManagerImplTest
FakeNearbyShareClientFactory nearby_client_factory_;
FakeNearbyShareLocalDeviceDataManager local_device_data_manager_;
std::unique_ptr<FakeAccountManager> account_manager_;
FakeNearbyShareSchedulerFactory scheduler_factory_;
std::unique_ptr<NearbyShareContactManager> manager_;
std::unique_ptr<NearbyShareContactManagerImpl> manager_;
};
} // namespace
+5 -8
View File
@@ -28,8 +28,7 @@
#include "sharing/internal/base/mime.h"
#include "sharing/proto/wire_format.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
namespace {
using ::location::nearby::proto::sharing::AttachmentSourceType;
@@ -61,12 +60,11 @@ FileAttachment::FileAttachment(FilePath file_path, absl::string_view mime_type,
std::string parent_folder, int32_t batch_id,
AttachmentSourceType source_type)
: Attachment(Attachment::Family::kFile, /*size=*/0, batch_id, source_type),
file_name_(file_path.GetFileName().ToString()),
mime_type_(mime_type.empty() ? MimeTypeFromPath(file_path) : mime_type),
type_(FileAttachmentTypeFromMimeType(mime_type_)),
parent_folder_(std::move(parent_folder)) {
file_name_ = file_path.GetFileName().ToString();
file_path_ = std::move(file_path);
}
parent_folder_(std::move(parent_folder)),
file_path_(std::move(file_path)) {}
FileAttachment::FileAttachment(int64_t id, int64_t size, std::string file_name,
std::string mime_type, Type type,
@@ -108,5 +106,4 @@ ShareType FileAttachment::GetShareType() const {
}
}
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
+6 -12
View File
@@ -39,8 +39,7 @@
#include "sharing/common/nearby_share_enums.h"
#include "sharing/proto/wire_format.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
// A single attachment to be sent by / received from a |ShareTarget|, can be
// either a file or text.
@@ -58,10 +57,6 @@ class FileAttachment : public Attachment {
Type type, std::string parent_folder = "", int32_t batch_id = 0,
location::nearby::proto::sharing::AttachmentSourceType source_type =
location::nearby::proto::sharing::ATTACHMENT_SOURCE_UNKNOWN);
FileAttachment(const FileAttachment&) = default;
FileAttachment(FileAttachment&&) = default;
FileAttachment& operator=(const FileAttachment&) = default;
FileAttachment& operator=(FileAttachment&&) = default;
~FileAttachment() override = default;
absl::string_view file_name() const { return file_name_; }
@@ -82,14 +77,13 @@ class FileAttachment : public Attachment {
private:
// File name should be in UTF8 format.
std::string file_name_;
std::string mime_type_;
Type type_;
const std::string file_name_;
const std::string mime_type_;
const Type type_;
const std::string parent_folder_;
std::optional<FilePath> file_path_;
std::string parent_folder_;
};
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
#endif // THIRD_PARTY_NEARBY_SHARING_FILE_ATTACHMENT_H_
@@ -53,32 +53,20 @@ constexpr auto kEnableSelfShareUi =
// Enable/disable sending desktop events
constexpr auto kEnableSendingDesktopEvents =
flags::Flag<bool>(kConfigPackage, "45459748", false);
// Disable/enable the WebRTC medium in Nearby Sharing SDK.
constexpr auto kEnableWebrtcMedium =
flags::Flag<bool>(kConfigPackage, "45411620", false);
// Set the logging level in Nearby Sharing SDK. The default logging level is
// WARNING. The mapping of logging level to number: INFO: 0, WARNING: 1, ERROR:
// 2, FATAL: 3, negative values are -(verbosity level).
constexpr auto kLoggingLevel =
flags::Flag<int64_t>(kConfigPackage, "45401358", 1);
// When true, the sender will not require confirming the ukey2 token.
constexpr auto kSenderSkipsConfirmation =
flags::Flag<bool>(kConfigPackage, "45411353", true);
// Enable/disable auto-update on settings page
constexpr auto kShowAutoUpdateSetting =
flags::Flag<bool>(kConfigPackage, "45409033", false);
// When true, use gRpc client to access backend.
constexpr auto kUseGrpcClient =
flags::Flag<bool>(kConfigPackage, "45630055", false);
// When true, delete the file payload which received unexpectedly.
constexpr auto kDeleteUnexpectedReceivedFileFix =
flags::Flag<bool>(kConfigPackage, "45657036", false);
// The default time in milliseconds a cached entry can be in LOST state.
constexpr auto kDiscoveryCacheLostExpiryMs =
flags::Flag<int64_t>(kConfigPackage, "45658774", 500);
// When true, enable Nearby Share gRPC async client.
constexpr auto kEnableNearbyShareGrpcAsyncClient =
flags::Flag<bool>(kConfigPackage, "45726584", false);
flags::Flag<int64_t>(kConfigPackage, "45658774", 15000);
// When true, enable wifi hotspot medium for HP Realtek devices.
constexpr auto kEnableWifiHotspotForHpRealtekDevices =
flags::Flag<bool>(kConfigPackage, "45673628", false);
@@ -89,12 +77,6 @@ constexpr auto kUnregisterTargetDiscoveryCacheLostExpiryMs =
// When true, enable alternate BLE service UUID for discovery.
constexpr auto kUseAlternateServiceUuidForDiscovery =
flags::Flag<bool>(kConfigPackage, "45683539", false);
// Enable/disable QR Code UI
constexpr auto kEnableQrCodeUi =
flags::Flag<bool>(kConfigPackage, "45417647", false);
// Show Admin mode warning message in the app
constexpr auto kShowAdminModeWarning =
flags::Flag<bool>(kConfigPackage, "45410558", false);
// Update track
constexpr auto kUpdateTrack =
flags::Flag<absl::string_view>(kConfigPackage, "45409861", "");
@@ -106,19 +88,19 @@ constexpr auto kEnableBetaLabel =
flags::Flag<bool>(kConfigPackage, "45662570", true);
// Enable the info banner to display duplicate Quick Share apps.
constexpr auto kEnableConflictBanner =
flags::Flag<bool>(kConfigPackage, "45661130", false);
flags::Flag<bool>(kConfigPackage, "45661130", true);
// When true, enables use of Flutter hooks.
constexpr auto kEnableFlutterHooks =
flags::Flag<bool>(kConfigPackage, "45720206", false);
// When true, enables the mini pulse animation.
constexpr auto kEnableMiniPulse =
flags::Flag<bool>(kConfigPackage, "45724244", false);
// When true, enables notifications implemented in native code.
constexpr auto kEnableNativeNotifications =
flags::Flag<bool>(kConfigPackage, "45743135", false);
// When true, enables responsive UI.
constexpr auto kEnableResponsiveUi =
flags::Flag<bool>(kConfigPackage, "45727212", false);
// When true, enables UI experiments.
constexpr auto kEnableUiExperiments =
flags::Flag<bool>(kConfigPackage, "45678202", false);
inline absl::btree_map<int, const flags::Flag<bool>&> GetBoolFlags() {
return {
@@ -129,22 +111,16 @@ inline absl::btree_map<int, const flags::Flag<bool>&> GetBoolFlags() {
{45411589, kEnableRetryResumeTransfer},
{45418908, kEnableSelfShareUi},
{45459748, kEnableSendingDesktopEvents},
{45411620, kEnableWebrtcMedium},
{45411353, kSenderSkipsConfirmation},
{45409033, kShowAutoUpdateSetting},
{45630055, kUseGrpcClient},
{45657036, kDeleteUnexpectedReceivedFileFix},
{45726584, kEnableNearbyShareGrpcAsyncClient},
{45673628, kEnableWifiHotspotForHpRealtekDevices},
{45683539, kUseAlternateServiceUuidForDiscovery},
{45417647, kEnableQrCodeUi},
{45410558, kShowAdminModeWarning},
{45662570, kEnableBetaLabel},
{45661130, kEnableConflictBanner},
{45720206, kEnableFlutterHooks},
{45724244, kEnableMiniPulse},
{45743135, kEnableNativeNotifications},
{45727212, kEnableResponsiveUi},
{45678202, kEnableUiExperiments},
};
}
+16 -9
View File
@@ -85,7 +85,15 @@ std::optional<TransferMetadata::Status>
IncomingShareSession::ProcessIntroduction(
const IntroductionFrame& introduction_frame) {
int64_t file_size_sum = 0;
AttachmentContainer& container = mutable_attachment_container();
int app_file_count = 0;
for (const AppMetadata& apk : introduction_frame.app_metadata()) {
app_file_count += apk.file_name_size();
}
AttachmentContainer::Builder builder;
builder.ReserveAttachmentsCount(
introduction_frame.text_metadata_size() + app_file_count,
introduction_frame.file_metadata_size(),
introduction_frame.wifi_credentials_metadata_size());
for (const auto& file : introduction_frame.file_metadata()) {
if (file.size() <= 0) {
LOG(WARNING) << "Ignore introduction, due to invalid attachment size";
@@ -97,7 +105,7 @@ IncomingShareSession::ProcessIntroduction(
<< ", payload_id=" << file.payload_id()
<< ", parent_folder=" << file.parent_folder()
<< ", mime_type=" << file.mime_type();
container.AddFileAttachment(
builder.AddFileAttachment(
FileAttachment(file.id(), file.size(), file.name(), file.mime_type(),
file.type(), file.parent_folder()));
SetAttachmentPayloadId(file.id(), file.payload_id());
@@ -105,7 +113,6 @@ IncomingShareSession::ProcessIntroduction(
if (std::numeric_limits<int64_t>::max() - file.size() < file_size_sum) {
LOG(WARNING) << "Ignoring introduction, total file size overflowed 64 "
"bit integer.";
container.Clear();
return TransferMetadata::Status::kNotEnoughSpace;
}
file_size_sum += file.size();
@@ -126,7 +133,6 @@ IncomingShareSession::ProcessIntroduction(
LOG(WARNING) << __func__
<< ": Ignoring introduction, total file size overflowed "
"64 bit integer.";
container.Clear();
return TransferMetadata::Status::kNotEnoughSpace;
}
// Map each apk file to a file attachment.
@@ -141,7 +147,7 @@ IncomingShareSession::ProcessIntroduction(
<< ", attachment id=" << apk_file_id
<< ", file size=" << apk.file_size(index)
<< ", payload_id=" << apk.payload_id(index);
container.AddFileAttachment(std::move(apk_file));
builder.AddFileAttachment(std::move(apk_file));
SetAttachmentPayloadId(apk_file_id, apk.payload_id(index));
}
file_size_sum += apk.size();
@@ -156,7 +162,7 @@ IncomingShareSession::ProcessIntroduction(
VLOG(1) << "Found text attachment: id=" << text.id()
<< ", type= " << text.type() << ", size=" << text.size()
<< ", payload_id=" << text.payload_id();
container.AddTextAttachment(
builder.AddTextAttachment(
TextAttachment(text.id(), text.type(), text.text_title(), text.size()));
SetAttachmentPayloadId(text.id(), text.payload_id());
}
@@ -167,7 +173,7 @@ IncomingShareSession::ProcessIntroduction(
VLOG(1) << "Found WiFi credentials attachment: id="
<< wifi_credentials.id() << ", ssid= " << wifi_credentials.ssid()
<< ", payload_id=" << wifi_credentials.payload_id();
container.AddWifiCredentialsAttachment(WifiCredentialsAttachment(
builder.AddWifiCredentialsAttachment(WifiCredentialsAttachment(
wifi_credentials.id(), wifi_credentials.ssid(),
wifi_credentials.security_type()));
SetAttachmentPayloadId(wifi_credentials.id(),
@@ -175,12 +181,13 @@ IncomingShareSession::ProcessIntroduction(
}
}
if (!container.HasAttachments()) {
if (builder.Empty()) {
LOG(WARNING) << __func__
<< ": No attachment is found for this share target. It can "
"be result of unrecognizable attachment type";
return TransferMetadata::Status::kUnsupportedAttachmentType;
}
mutable_attachment_container() = std::move(*builder.Build());
return std::nullopt;
}
@@ -305,7 +312,7 @@ bool IncomingShareSession::UpdateFilePayloadPaths() {
continue;
}
FilePath file_path = incoming_payload->content.file_payload.file.path;
FilePath file_path = incoming_payload->content.file_payload.file_path;
VLOG(1) << __func__ << ": Updated file_path=" << file_path.ToString();
file.set_file_path(file_path);
}
+1 -4
View File
@@ -89,8 +89,7 @@ constexpr absl::string_view kEndpointId = "ABCD";
std::unique_ptr<Payload> CreateFilePayload(int64_t payload_id,
FilePath file_path) {
auto file_payload =
std::make_unique<Payload>(InputFile(file_path.ToString()));
auto file_payload = std::make_unique<Payload>(file_path);
file_payload->id = payload_id;
return file_payload;
}
@@ -218,7 +217,6 @@ TEST_F(IncomingShareSessionTest, ProcessIntroductionNoSupportedPayload) {
TEST_F(IncomingShareSessionTest, ProcessIntroductionEmptyFile) {
session_.OnConnected(&connection_);
IntroductionFrame frame;
frame.mutable_file_metadata();
EXPECT_THAT(session_.ProcessIntroduction(frame),
Eq(TransferMetadata::Status::kUnsupportedAttachmentType));
@@ -243,7 +241,6 @@ TEST_F(IncomingShareSessionTest, ProcessIntroductionFilesTooLarge) {
TEST_F(IncomingShareSessionTest, ProcessIntroductionEmptyText) {
session_.OnConnected(&connection_);
IntroductionFrame frame;
frame.mutable_text_metadata();
EXPECT_THAT(session_.ProcessIntroduction(frame),
Eq(TransferMetadata::Status::kUnsupportedAttachmentType));
+1 -3
View File
@@ -23,15 +23,13 @@ namespace nearby::sharing::api {
class MockNetworkMonitor : public nearby::api::NetworkMonitor {
public:
MockNetworkMonitor() : nearby::api::NetworkMonitor(nullptr) {}
MockNetworkMonitor() : nearby::api::NetworkMonitor(nullptr, nullptr) {}
MockNetworkMonitor(const MockNetworkMonitor&) = delete;
MockNetworkMonitor& operator=(const MockNetworkMonitor&) = delete;
~MockNetworkMonitor() override = default;
MOCK_METHOD(bool, IsLanConnected, (), (override));
MOCK_METHOD(bool, IsInternetConnected, (), (override));
MOCK_METHOD(ConnectionType, GetCurrentConnection, (), (override));
};
} // namespace nearby::sharing::api
+3 -4
View File
@@ -48,13 +48,12 @@ class MockSharingPlatform : public SharingPlatform {
~MockSharingPlatform() override = default;
MOCK_METHOD(void, InitProductIdGetter,
(absl::string_view (*product_id_getter)()), (override));
(absl::string_view(*product_id_getter)()), (override));
MOCK_METHOD(std::unique_ptr<nearby::api::NetworkMonitor>,
CreateNetworkMonitor,
(std::function<void(nearby::api::NetworkMonitor::ConnectionType,
bool, bool)>
callback),
(std::function<void(bool)> lan_connected_callback,
std::function<void(bool)> internet_connected_callback),
(override));
MOCK_METHOD(nearby::sharing::api::BluetoothAdapter&, GetBluetoothAdapter, (),
+12 -27
View File
@@ -15,36 +15,23 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_INTERNAL_API_NETWORK_MONITOR_H_
#define THIRD_PARTY_NEARBY_SHARING_INTERNAL_API_NETWORK_MONITOR_H_
#include <functional>
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
namespace nearby {
namespace api {
class NetworkMonitor {
public:
enum class ConnectionType : int {
kUnknown = 0, // A connection exists, but its type is unknown.
// Also used as a default value.
kEthernet = 1,
kWifi = 2,
k2G = 3,
k3G = 4,
k4G = 5,
kNone = 6, // No connection.
kBluetooth = 7,
k5G = 8,
kLast = k5G
};
// Registers a callback for connection changes. The callback will be called
// with the current connection type, whether the device is connected to a
// LAN network and whether the device is connected to internet.
explicit NetworkMonitor(
std::function<void(ConnectionType, bool, bool)> callback) {
callback_ = std::move(callback);
}
// Registers callbacks for connection changes. The callbacks will be called
// when device is connected to a LAN network or when the device is connected
// to internet.
NetworkMonitor(
absl::AnyInvocable<void(bool)> lan_connected_callback,
absl::AnyInvocable<void(bool)> internet_connected_callback)
: lan_connected_callback_(std::move(lan_connected_callback)),
internet_connected_callback_(std::move(internet_connected_callback)){}
virtual ~NetworkMonitor() = default;
@@ -55,11 +42,9 @@ class NetworkMonitor {
// Returns true if connected to internet.
virtual bool IsInternetConnected() = 0;
// Returns the type of connection used currently to access the internet
virtual ConnectionType GetCurrentConnection() = 0;
protected:
std::function<void(ConnectionType, bool, bool)> callback_;
absl::AnyInvocable<void(bool)> lan_connected_callback_;
absl::AnyInvocable<void(bool)> internet_connected_callback_;
};
} // namespace api
+2 -3
View File
@@ -48,9 +48,8 @@ class SharingPlatform {
absl::string_view (*product_id_getter)()) = 0;
virtual std::unique_ptr<nearby::api::NetworkMonitor> CreateNetworkMonitor(
std::function<void(nearby::api::NetworkMonitor::ConnectionType, bool,
bool)>
callback) = 0;
std::function<void(bool)> lan_connected_callback,
std::function<void(bool)> internet_connected_callback) = 0;
virtual BluetoothAdapter& GetBluetoothAdapter() = 0;
+1 -4
View File
@@ -55,23 +55,20 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":logging",
":types",
"//internal/flags:nearby_flags",
"//internal/network:url",
"//internal/platform:types",
"//sharing/flags/generated:generated_flags",
"//sharing/internal/api:platform",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
],
)
cc_test(
name = "nearby_context_test",
name = "connectivity_manager_impl_test",
size = "small",
timeout = "short",
srcs = [
+9 -23
View File
@@ -23,35 +23,21 @@ namespace nearby {
class ConnectivityManager {
public:
enum class ConnectionType {
kUnknown = 0, // A connection exists, but its type is unknown.
// Also used as a default value.
kEthernet = 1,
kWifi = 2,
k2G = 3,
k3G = 4,
k4G = 5,
kNone = 6, // No connection.
kBluetooth = 7,
k5G = 8,
kLast = k5G
};
virtual ~ConnectivityManager() = default;
virtual bool IsLanConnected() = 0;
virtual bool IsInternetConnected() = 0;
virtual ConnectionType GetConnectionType() = 0;
// Registers a listener for connection changes. The listener will be called
// with the current connection type, whether the device is connected to a
// LAN network and whether the device is connected to internet.
virtual void RegisterConnectionListener(
absl::string_view listener_name,
std::function<void(ConnectionType, bool, bool)>) = 0;
virtual void UnregisterConnectionListener(
absl::string_view listener_name) = 0;
// when the device is connected to a LAN network or when the device is
// connected to internet.
virtual void RegisterLanListener(absl::string_view listener_name,
std::function<void(bool)>) = 0;
virtual void UnregisterLanListener(absl::string_view listener_name) = 0;
virtual void RegisterInternetListener(absl::string_view listener_name,
std::function<void(bool)>) = 0;
virtual void UnregisterInternetListener(absl::string_view listener_name) = 0;
// Is the device a HP device with Realtek wireless module.
virtual bool IsHPRealtekDevice() = 0;
};
@@ -18,7 +18,6 @@
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "absl/container/flat_hash_map.h"
@@ -29,50 +28,27 @@
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
#include "sharing/internal/api/network_monitor.h"
#include "sharing/internal/api/sharing_platform.h"
#include "sharing/internal/public/connectivity_manager.h"
#include "sharing/internal/public/logging.h"
namespace nearby {
namespace {
using ::nearby::sharing::api::SharingPlatform;
using ConnectionType = ConnectivityManager::ConnectionType;
std::string GetConnectionTypeString(ConnectionType connection_type) {
switch (connection_type) {
case ConnectionType::k2G:
return "2G";
case ConnectionType::k3G:
return "3G";
case ConnectionType::k4G:
return "4G";
case ConnectionType::k5G:
return "5G";
case ConnectionType::kBluetooth:
return "Bluetooth";
case ConnectionType::kEthernet:
return "Ethernet";
case ConnectionType::kWifi:
return "WiFi";
default:
return "Unknown";
}
}
} // namespace
ConnectivityManagerImpl::ConnectivityManagerImpl(SharingPlatform& platform)
: platform_(platform) {
network_monitor_ = platform.CreateNetworkMonitor(
[this](api::NetworkMonitor::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {
ConnectionType new_connection_type =
static_cast<ConnectionType>(connection_type);
VLOG(1) << ": New connection type:"
<< GetConnectionTypeString(new_connection_type);
for (auto& listener : listeners_) {
listener.second(new_connection_type, is_lan_connected,
is_internet_connected);
[this](bool is_lan_connected) {
absl::MutexLock lock(mutex_);
for (auto& listener : lan_listeners_) {
listener.second(is_lan_connected);
}
},
[this](bool is_internet_connected) {
absl::MutexLock lock(mutex_);
for (auto& listener : internet_listeners_) {
listener.second(is_internet_connected);
}
});
}
@@ -113,23 +89,37 @@ bool ConnectivityManagerImpl::IsHPRealtekDevice() {
return is_hp_realtek_device_.value();
}
ConnectionType ConnectivityManagerImpl::GetConnectionType() {
return static_cast<ConnectionType>(network_monitor_->GetCurrentConnection());
void ConnectivityManagerImpl::RegisterLanListener(
absl::string_view listener_name, std::function<void(bool)> callback) {
absl::MutexLock lock(mutex_);
lan_listeners_.emplace(listener_name, std::move(callback));
}
void ConnectivityManagerImpl::RegisterConnectionListener(
absl::string_view listener_name,
std::function<void(ConnectionType, bool, bool)> callback) {
listeners_.emplace(listener_name, std::move(callback));
}
void ConnectivityManagerImpl::UnregisterConnectionListener(
void ConnectivityManagerImpl::UnregisterLanListener(
absl::string_view listener_name) {
listeners_.erase(listener_name);
absl::MutexLock lock(mutex_);
lan_listeners_.erase(listener_name);
}
int ConnectivityManagerImpl::GetListenerCount() const {
return listeners_.size();
void ConnectivityManagerImpl::RegisterInternetListener(
absl::string_view listener_name, std::function<void(bool)> callback) {
absl::MutexLock lock(mutex_);
internet_listeners_.emplace(listener_name, std::move(callback));
}
void ConnectivityManagerImpl::UnregisterInternetListener(
absl::string_view listener_name) {
absl::MutexLock lock(mutex_);
internet_listeners_.erase(listener_name);
}
int ConnectivityManagerImpl::GetLanListenerCountForTests() const {
absl::MutexLock lock(mutex_);
return lan_listeners_.size();
}
int ConnectivityManagerImpl::GetInternetListenerCountForTests() const {
absl::MutexLock lock(mutex_);
return internet_listeners_.size();
}
} // namespace nearby
@@ -26,7 +26,6 @@
#include "absl/synchronization/mutex.h"
#include "sharing/internal/api/network_monitor.h"
#include "sharing/internal/api/sharing_platform.h"
#include "sharing/internal/api/system_info.h"
#include "sharing/internal/public/connectivity_manager.h"
namespace nearby {
@@ -40,19 +39,22 @@ class ConnectivityManagerImpl : public ConnectivityManager {
bool IsLanConnected() override;
bool IsInternetConnected() override;
bool IsHPRealtekDevice() override;
ConnectionType GetConnectionType() override;
void RegisterConnectionListener(
absl::string_view listener_name,
std::function<void(ConnectionType, bool, bool)> callback) override;
void UnregisterConnectionListener(absl::string_view listener_name) override;
void RegisterLanListener(absl::string_view listener_name,
std::function<void(bool)>) override;
void UnregisterLanListener(absl::string_view listener_name) override;
void RegisterInternetListener(absl::string_view listener_name,
std::function<void(bool)>) override;
void UnregisterInternetListener(absl::string_view listener_name) override;
int GetListenerCount() const;
int GetLanListenerCountForTests() const;
int GetInternetListenerCountForTests() const;
private:
absl::flat_hash_map<std::string,
std::function<void(ConnectionType, bool, bool)>>
listeners_;
absl::flat_hash_map<std::string, std::function<void(bool)>> lan_listeners_
ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<std::string, std::function<void(bool)>>
internet_listeners_ ABSL_GUARDED_BY(mutex_);
std::unique_ptr<api::NetworkMonitor> network_monitor_;
nearby::sharing::api::SharingPlatform& platform_;
mutable absl::Mutex mutex_;
@@ -42,25 +42,24 @@ TEST(ConnectivityManagerImpl, IsLanConnected) {
auto network_monitor = std::make_unique<MockNetworkMonitor>();
MockNetworkMonitor* mock_network_monitor = network_monitor.get();
EXPECT_CALL(*mock_network_monitor, IsLanConnected()).WillOnce(Return(true));
EXPECT_CALL(sharing_platform, CreateNetworkMonitor(_))
EXPECT_CALL(sharing_platform, CreateNetworkMonitor(_, _))
.WillOnce(Return(ByMove(std::move(network_monitor))));
ConnectivityManagerImpl connectivity_manager_impl(sharing_platform);
EXPECT_TRUE(connectivity_manager_impl.IsLanConnected());
}
TEST(ConnectivityManagerImpl, GetConnectionType) {
TEST(ConnectivityManagerImpl, IsInternetConnected) {
MockSharingPlatform sharing_platform;
auto network_monitor = std::make_unique<MockNetworkMonitor>();
MockNetworkMonitor* mock_network_monitor = network_monitor.get();
EXPECT_CALL(sharing_platform, CreateNetworkMonitor(_))
EXPECT_CALL(*mock_network_monitor, IsInternetConnected())
.WillOnce(Return(true));
EXPECT_CALL(sharing_platform, CreateNetworkMonitor(_, _))
.WillOnce(Return(ByMove(std::move(network_monitor))));
EXPECT_CALL(*mock_network_monitor, GetCurrentConnection())
.WillOnce(Return(MockNetworkMonitor::ConnectionType::kWifi));
ConnectivityManagerImpl connectivity_manager_impl(sharing_platform);
EXPECT_EQ(connectivity_manager_impl.GetConnectionType(),
ConnectivityManager::ConnectionType::kWifi);
EXPECT_TRUE(connectivity_manager_impl.IsInternetConnected());
}
TEST(ConnectivityManagerImpl, IsHPRealtekDeviceReturnsTrue) {
@@ -111,49 +110,43 @@ TEST(ConnectivityManagerImpl, IsHPRealtekDevice_NotRealtekDevice) {
EXPECT_FALSE(connectivity_manager_impl.IsHPRealtekDevice());
}
TEST(ConnectivityManagerImpl, RegisterConnectionListener) {
std::function<void(ConnectivityManager::ConnectionType, bool, bool)>
listener_1 = [](ConnectivityManager::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {};
std::function<void(ConnectivityManager::ConnectionType, bool, bool)>
listener_2 = [](ConnectivityManager::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {};
TEST(ConnectivityManagerImpl, RegisterLanListener) {
auto
listener_1 = [](bool is_lan_connected) {};
auto
listener_2 = [](bool is_lan_connected) {};
MockSharingPlatform sharing_platform;
ConnectivityManagerImpl connectivity_manager_impl(sharing_platform);
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 0);
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 0);
connectivity_manager_impl.RegisterConnectionListener("listener_1",
connectivity_manager_impl.RegisterLanListener("listener_1",
listener_1);
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 1);
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 1);
connectivity_manager_impl.RegisterConnectionListener("listener_2",
connectivity_manager_impl.RegisterLanListener("listener_2",
listener_2);
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 2);
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 2);
}
TEST(ConnectivityManagerImpl, UnregisterConnectionListener) {
std::function<void(ConnectivityManager::ConnectionType, bool, bool)>
listener_1 = [](ConnectivityManager::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {};
std::function<void(ConnectivityManager::ConnectionType, bool, bool)>
listener_2 = [](ConnectivityManager::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {};
TEST(ConnectivityManagerImpl, UnregisterLanListener) {
auto listener_1 = [](bool is_lan_connected) {};
auto listener_2 = [](bool is_lan_connected) {};
MockSharingPlatform sharing_platform;
ConnectivityManagerImpl connectivity_manager_impl(sharing_platform);
connectivity_manager_impl.RegisterConnectionListener("listener_1",
connectivity_manager_impl.RegisterLanListener("listener_1",
listener_1);
connectivity_manager_impl.RegisterConnectionListener("listener_2",
connectivity_manager_impl.RegisterLanListener("listener_2",
listener_2);
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 2);
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 2);
connectivity_manager_impl.UnregisterConnectionListener("listener_1");
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 1);
connectivity_manager_impl.UnregisterLanListener("listener_1");
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 1);
connectivity_manager_impl.UnregisterConnectionListener("listener_2");
EXPECT_EQ(connectivity_manager_impl.GetListenerCount(), 0);
connectivity_manager_impl.UnregisterLanListener("listener_2");
EXPECT_EQ(connectivity_manager_impl.GetLanListenerCountForTests(), 0);
}
} // namespace
-1
View File
@@ -31,7 +31,6 @@ cc_library(
"fake_connectivity_manager.h",
"fake_context.h",
"fake_fast_initiation_manager.h",
"fake_network_monitor.h",
"fake_preference_manager.h",
"fake_public_certificate_db.h",
],
@@ -33,52 +33,43 @@ class FakeConnectivityManager : public ConnectivityManager {
void SetIsHPRealtekDevice(bool is_hp_realtek_device) {
is_hp_realtek_device_ = is_hp_realtek_device;
}
ConnectionType GetConnectionType() override { return connection_type_; }
void RegisterConnectionListener(
absl::string_view listener_name,
std::function<void(ConnectionType, bool, bool)> callback) override {
listeners_.emplace(listener_name, std::move(callback));
void RegisterLanListener(absl::string_view listener_name,
std::function<void(bool)> callback) override {
lan_listeners_.emplace(listener_name, std::move(callback));
}
void UnregisterConnectionListener(absl::string_view listener_name) override {
listeners_.erase(listener_name);
void UnregisterLanListener(absl::string_view listener_name) override {
lan_listeners_.erase(listener_name);
}
void RegisterInternetListener(absl::string_view listener_name,
std::function<void(bool)> callback) override {
internet_listeners_.emplace(listener_name, std::move(callback));
}
void UnregisterInternetListener(absl::string_view listener_name) override {
internet_listeners_.erase(listener_name);
}
// Mocks connectivity methods.
void SetLanConnected(bool connected) {
is_lan_connected_ = connected;
for (auto& listener : listeners_) {
listener.second(connection_type_, is_lan_connected_,
is_internet_connected_);
for (auto& listener : lan_listeners_) {
listener.second(is_lan_connected_);
}
}
void SetInternetConnected(bool connected) {
is_internet_connected_ = connected;
for (auto& listener : listeners_) {
listener.second(connection_type_, is_lan_connected_,
is_internet_connected_);
for (auto& listener : internet_listeners_) {
listener.second(is_internet_connected_);
}
}
// Mocks connectivity methods.
void SetConnectionType(ConnectionType connection_type) {
connection_type_ = connection_type;
for (auto& listener : listeners_) {
listener.second(connection_type_, is_lan_connected_,
is_internet_connected_);
}
}
int GetListenerCount() const { return listeners_.size(); }
private:
bool is_lan_connected_ = true;
bool is_internet_connected_ = true;
bool is_hp_realtek_device_ = false;
ConnectionType connection_type_ = ConnectionType::kWifi;
absl::flat_hash_map<std::string,
std::function<void(ConnectionType, bool, bool)>>
listeners_;
absl::flat_hash_map<std::string, std::function<void(bool)>> lan_listeners_;
absl::flat_hash_map<std::string, std::function<void(bool)>>
internet_listeners_;
};
} // namespace nearby
@@ -15,7 +15,6 @@
#include "sharing/internal/test/fake_connectivity_manager.h"
#include "gtest/gtest.h"
#include "sharing/internal/public/connectivity_manager.h"
namespace nearby {
namespace {
@@ -28,40 +27,16 @@ TEST(FakeConnectivityManager, TestIsLanConnected) {
EXPECT_FALSE(connection_manager.IsLanConnected());
}
TEST(FakeConnectivityManager, TestGetCurrentConnection) {
FakeConnectivityManager connection_manager;
ConnectivityManager::ConnectionType connection =
connection_manager.GetConnectionType();
EXPECT_EQ(connection, ConnectivityManager::ConnectionType::kWifi);
connection_manager.SetConnectionType(
ConnectivityManager::ConnectionType::kEthernet);
EXPECT_EQ(connection_manager.GetConnectionType(),
ConnectivityManager::ConnectionType::kEthernet);
}
TEST(FakeConnectivityManager, TestListener) {
FakeConnectivityManager connection_manager;
ConnectivityManager::ConnectionType connection_type =
connection_manager.GetConnectionType();
bool is_lan_connected = false;
connection_manager.RegisterConnectionListener(
"test", [&connection_type, &is_lan_connected](
ConnectivityManager::ConnectionType connection,
bool connected, bool internet_connected) {
connection_type = connection;
is_lan_connected = connected;
connection_manager.RegisterLanListener(
"test", [&is_lan_connected](bool lan_connected) {
is_lan_connected = lan_connected;
});
EXPECT_EQ(connection_manager.GetListenerCount(), 1);
connection_manager.SetConnectionType(
ConnectivityManager::ConnectionType::kEthernet);
connection_manager.SetLanConnected(true);
EXPECT_EQ(connection_type, ConnectivityManager::ConnectionType::kEthernet);
ASSERT_TRUE(is_lan_connected);
connection_manager.UnregisterConnectionListener("test");
EXPECT_EQ(connection_manager.GetListenerCount(), 0);
connection_manager.SetConnectionType(
ConnectivityManager::ConnectionType::kWifi);
EXPECT_EQ(connection_type, ConnectivityManager::ConnectionType::kEthernet);
connection_manager.UnregisterLanListener("test");
EXPECT_TRUE(is_lan_connected);
}
@@ -1,57 +0,0 @@
// Copyright 2022 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 THIRD_PARTY_NEARBY_SHARING_INTERNAL_TEST_FAKE_NETWORK_MONITOR_H_
#define THIRD_PARTY_NEARBY_SHARING_INTERNAL_TEST_FAKE_NETWORK_MONITOR_H_
#include <functional>
#include "sharing/internal/api/network_monitor.h"
namespace nearby {
class FakeNetworkMonitor : public api::NetworkMonitor {
public:
explicit FakeNetworkMonitor(
std::function<void(api::NetworkMonitor::ConnectionType, bool, bool)>
callback)
: api::NetworkMonitor(callback) {}
~FakeNetworkMonitor() override { callback_ = nullptr; }
bool IsLanConnected() override { return is_lan_connected_; }
bool IsInternetConnected() override { return is_internet_connected_; }
api::NetworkMonitor::ConnectionType GetCurrentConnection() override {
return api::NetworkMonitor::ConnectionType::kWifi;
}
void SetLanConnected(bool connected) { is_lan_connected_ = connected; }
void SetInternetConnected(bool connected) {
is_internet_connected_ = connected;
}
void TestNetworkChangeToEthernet() {
callback_(api::NetworkMonitor::ConnectionType::kEthernet,
is_lan_connected_, is_internet_connected_);
}
private:
bool is_lan_connected_ = true;
bool is_internet_connected_ = true;
};
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_SHARING_INTERNAL_TEST_FAKE_NETWORK_MONITOR_H_
+5 -14
View File
@@ -72,17 +72,14 @@ bool ShouldUseInternet(ConnectivityManager& connectivity_manager,
// We won't use the internet in a low power mode.
if (power_level == PowerLevel::kLowPower) return false;
ConnectivityManager::ConnectionType connection_type =
connectivity_manager.GetConnectionType();
// Verify that this network has an internet connection.
if (connection_type == ConnectivityManager::ConnectionType::kNone) {
if (!connectivity_manager.IsInternetConnected()) {
VLOG(1) << __func__ << ": No internet connection.";
return false;
}
if (data_usage == DataUsage::WIFI_ONLY_DATA_USAGE &&
connection_type != ConnectivityManager::ConnectionType::kWifi) {
!connectivity_manager.IsLanConnected()) {
return false;
}
@@ -105,13 +102,7 @@ bool ShouldEnableWifiLan(ConnectivityManager& connectivity_manager) {
return false;
}
ConnectivityManager::ConnectionType connection_type =
connectivity_manager.GetConnectionType();
bool is_connection_wifi_or_ethernet =
connection_type == ConnectivityManager::ConnectionType::kWifi ||
connection_type == ConnectivityManager::ConnectionType::kEthernet;
return is_connection_wifi_or_ethernet;
return connectivity_manager.IsLanConnected();
}
// Temporarily fix to get around wifi hotspot issues for HP Aero with Realtek.
@@ -818,7 +809,7 @@ void NearbyConnectionsManagerImpl::DeleteUnknownFilePayloadAndCancel(
Payload& payload) {
if (payload.content.type == PayloadContent::Type::kFile) {
MutexLock lock(&mutex_);
file_paths_to_delete_.insert(payload.content.file_payload.file.path);
file_paths_to_delete_.insert(payload.content.file_payload.file_path);
}
Cancel(payload.id);
}
@@ -909,7 +900,7 @@ void NearbyConnectionsManagerImpl::OnPayloadTransferUpdate(
nearby_connections_service_->CancelPayload(kServiceId, payload->id,
[](Status status) {});
ProcessUnknownFilePathsToDelete(update.status, payload->content.type,
payload->content.file_payload.file.path);
payload->content.file_payload.file_path);
return;
}
}
+67 -72
View File
@@ -16,7 +16,6 @@
#include <stdint.h>
#include <cstdio>
#include <fstream>
#include <functional>
#include <ios>
@@ -39,14 +38,13 @@
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/flags/nearby_flags.h"
#include "internal/test/fake_clock.h"
#include "internal/test/fake_device_info.h"
#include "internal/test/fake_task_runner.h"
#include "sharing/common/nearby_share_enums.h"
#include "sharing/constants.h"
#include "sharing/fake_nearby_connections_service.h"
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
#include "sharing/internal/public/connectivity_manager.h"
#include "sharing/internal/public/logging.h"
#include "sharing/internal/test/fake_connectivity_manager.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/nearby_connection.h"
@@ -142,7 +140,6 @@ class NearbyConnectionsManagerImplTest : public testing::Test {
true);
auto nearby_connections_service =
std::make_unique<testing::NiceMock<FakeNearbyConnectionsService>>();
SetConnectionType(ConnectivityManager::ConnectionType::kWifi);
nearby_connections_ = nearby_connections_service.get();
nearby_connections_manager_ =
@@ -156,10 +153,10 @@ class NearbyConnectionsManagerImplTest : public testing::Test {
fake_task_runner_.SyncWithTimeout(absl::Seconds(1));
}
void SetConnectionType(ConnectivityManager::ConnectionType connection_type) {
fake_connectivity_manager_.SetConnectionType(connection_type);
void SetConnectionStatus(bool lan_connected, bool internet_connected) {
fake_connectivity_manager_.SetLanConnected(lan_connected);
fake_connectivity_manager_.SetInternetConnected(internet_connected);
}
void Fastforward(absl::Duration duration) {
fake_context_.fake_clock()->FastForward(duration);
}
@@ -241,8 +238,7 @@ class NearbyConnectionsManagerImplTest : public testing::Test {
nearby_connections_manager_->StartAdvertising(
local_endpoint_info, &incoming_connection_listener,
PowerLevel::kHighPower, DataUsage::ONLINE_DATA_USAGE, false,
/*force_new_endpoint_id=*/false,
std::move(callback));
/*force_new_endpoint_id=*/false, std::move(callback));
EXPECT_TRUE(
notification.WaitForNotificationWithTimeout(kSynchronizationTimeOut));
}
@@ -407,13 +403,13 @@ class NearbyConnectionsManagerImplTest : public testing::Test {
EXPECT_EQ(payload_id, payload->id);
FilePayload file_payload = std::move(payload->content.file_payload);
std::vector<uint8_t> payload_bytes(file_payload.size);
std::ifstream payload_stream(file_payload.file.path.GetPath(),
std::vector<uint8_t> payload_bytes(expected_payload.size());
std::ifstream payload_stream(file_payload.file_path.GetPath(),
std::ios::in | std::ios::binary);
ASSERT_TRUE(payload_stream.good());
payload_stream.read(reinterpret_cast<char*>(payload_bytes.data()),
file_payload.size);
ASSERT_EQ(payload_stream.gcount(), file_payload.size);
payload_bytes.size());
ASSERT_EQ(payload_stream.gcount(), payload_bytes.size());
EXPECT_EQ(expected_payload, payload_bytes);
payload_stream.close();
@@ -423,7 +419,7 @@ class NearbyConnectionsManagerImplTest : public testing::Test {
// Manually setup payload id, because the tested id is not generated from
// file name.
auto payload = std::make_unique<Payload>(InputFile(file.ToString()));
auto payload = std::make_unique<Payload>(file);
payload->id = payload_id;
nearby_connections_manager_->Send(kRemoteEndpointId, std::move(payload),
@@ -532,7 +528,6 @@ TEST_F(NearbyConnectionsManagerImplTest, DiscoveryFlow) {
TEST_F(NearbyConnectionsManagerImplTest,
DisableWifiHotspotForHighQualityNonDisruptiveTransport) {
SetConnectionType(ConnectivityManager::ConnectionType::kWifi);
// StartDiscovery will succeed.
NearbyConnectionsService::DiscoveryListener discovery_listener_remote;
testing::NiceMock<MockDiscoveryListener> discovery_listener;
@@ -569,7 +564,6 @@ TEST_F(NearbyConnectionsManagerImplTest,
}
TEST_F(NearbyConnectionsManagerImplTest, DisableWifiHotspotForHPRealtekDevice) {
SetConnectionType(ConnectivityManager::ConnectionType::kWifi);
fake_connectivity_manager_.SetIsHPRealtekDevice(true);
// StartDiscovery will succeed.
@@ -611,7 +605,9 @@ TEST_F(NearbyConnectionsManagerImplTest, DisableWifiHotspotForHPRealtekDevice) {
// Begin: NearbyConnectionsManagerImplTestConnectionMediums
/******************************************************************************/
using ConnectionMediumsTestParam =
std::tuple<DataUsage, ConnectivityManager::ConnectionType, bool, bool>;
std::tuple<DataUsage, /*is_webrtc_enabled=*/bool,
/*is_wifilan_enabled=*/bool, /*is_lan_connected=*/bool,
/*is_internet_connected=*/bool>;
class NearbyConnectionsManagerImplTestConnectionMediums
: public NearbyConnectionsManagerImplTest,
public testing::WithParamInterface<ConnectionMediumsTestParam> {};
@@ -620,9 +616,15 @@ TEST_P(NearbyConnectionsManagerImplTestConnectionMediums,
RequestConnection_MediumSelection) {
const ConnectionMediumsTestParam& param = GetParam();
DataUsage data_usage = std::get<0>(param);
ConnectivityManager::ConnectionType connection_type = std::get<1>(param);
bool is_webrtc_enabled = std::get<2>(GetParam());
bool is_wifilan_enabled = std::get<3>(GetParam());
bool is_webrtc_enabled = std::get<1>(GetParam());
bool is_wifilan_enabled = std::get<2>(GetParam());
bool is_lan_connected = std::get<3>(GetParam());
bool is_internet_connected = std::get<4>(GetParam());
LOG(INFO) << "Test params: data_usage: " << static_cast<int>(data_usage)
<< ", is_webrtc_enabled: " << is_webrtc_enabled
<< ", is_wifilan_enabled: " << is_wifilan_enabled
<< ", is_lan_connected: " << is_lan_connected
<< ", is_internet_connected: " << is_internet_connected;
if (is_webrtc_enabled) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
@@ -642,18 +644,13 @@ TEST_P(NearbyConnectionsManagerImplTestConnectionMediums,
config_package_nearby::nearby_sharing_feature::kEnableMediumWifiLan,
false);
}
SetConnectionStatus(is_lan_connected, is_internet_connected);
SetConnectionType(connection_type);
bool should_use_internet =
data_usage != DataUsage::OFFLINE_DATA_USAGE &&
connection_type != ConnectivityManager::ConnectionType::kNone &&
!(data_usage == DataUsage::WIFI_ONLY_DATA_USAGE &&
connection_type != ConnectivityManager::ConnectionType::kWifi);
bool is_connection_wifi_or_ethernet =
connection_type == ConnectivityManager::ConnectionType::kWifi ||
connection_type == ConnectivityManager::ConnectionType::kEthernet;
is_internet_connected && data_usage != DataUsage::OFFLINE_DATA_USAGE &&
!(data_usage == DataUsage::WIFI_ONLY_DATA_USAGE && !is_lan_connected);
should_use_web_rtc_ = is_webrtc_enabled && should_use_internet;
should_use_wifilan_ = is_wifilan_enabled && is_connection_wifi_or_ethernet;
should_use_wifilan_ = is_wifilan_enabled && is_lan_connected;
MediumSelection expected_mediums(/*bluetooth=*/true,
/*ble=*/false,
@@ -707,10 +704,8 @@ INSTANTIATE_TEST_SUITE_P(
testing::Combine(testing::Values(DataUsage::WIFI_ONLY_DATA_USAGE,
DataUsage::OFFLINE_DATA_USAGE,
DataUsage::ONLINE_DATA_USAGE),
testing::Values(ConnectivityManager::ConnectionType::kNone,
ConnectivityManager::ConnectionType::kWifi,
ConnectivityManager::ConnectionType::k3G),
testing::Bool(), testing::Bool()));
testing::Bool(), testing::Bool(), testing::Bool(),
testing::Bool()));
/******************************************************************************/
// End: NearbyConnectionsManagerImplTestConnectionMediums
/******************************************************************************/
@@ -1413,10 +1408,10 @@ TEST_F(NearbyConnectionsManagerImplTest,
InitializeTemporaryFile(file1);
InitializeTemporaryFile(file2);
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId, InputFile(file1.ToString())));
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId2, InputFile(file2.ToString())));
payload_listener_remote.payload_cb(kRemoteEndpointId,
Payload(kPayloadId, file1));
payload_listener_remote.payload_cb(kRemoteEndpointId,
Payload(kPayloadId2, file2));
const std::vector<uint8_t> byte_payload(std::begin(kBytePayload),
std::end(kBytePayload));
@@ -1527,7 +1522,7 @@ TEST_F(NearbyConnectionsManagerImplTest, IncomingFilePayload) {
InitializeTemporaryFile(file);
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId, InputFile(file.ToString())));
kRemoteEndpointId, Payload(kPayloadId, file));
absl::Notification payload_notification;
EXPECT_CALL(*payload_listener, OnStatusUpdate(::testing::_)).WillOnce([&]() {
@@ -1545,14 +1540,14 @@ TEST_F(NearbyConnectionsManagerImplTest, IncomingFilePayload) {
nearby_connections_manager_->GetIncomingPayload(kPayloadId);
ASSERT_NE(payload, nullptr);
ASSERT_TRUE(payload->content.is_file());
std::vector<uint8_t> payload_bytes(payload->content.file_payload.size);
std::vector<uint8_t> payload_bytes(expected_payload.size());
std::ifstream payload_stream(
payload->content.file_payload.file.path.GetPath(),
payload->content.file_payload.file_path.GetPath(),
std::ios::in | std::ios::binary);
ASSERT_TRUE(payload_stream.good());
payload_stream.read(reinterpret_cast<char*>(payload_bytes.data()),
payload->content.file_payload.size);
ASSERT_EQ(payload_stream.gcount(), payload->content.file_payload.size);
payload_bytes.size());
ASSERT_EQ(payload_stream.gcount(), payload_bytes.size());
payload_stream.close();
EXPECT_EQ(payload_bytes, expected_payload);
}
@@ -1577,8 +1572,8 @@ TEST_F(NearbyConnectionsManagerImplTest, ClearIncomingPayloads) {
FilePath file = Files::GetTemporaryDirectory().append(FilePath("file.jpg"));
InitializeTemporaryFile(file);
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId, InputFile(file.ToString())));
payload_listener_remote.payload_cb(kRemoteEndpointId,
Payload(kPayloadId, file));
absl::Notification payload_notification;
EXPECT_CALL(*payload_listener, OnStatusUpdate(::testing::_)).WillOnce([&]() {
@@ -1602,8 +1597,9 @@ TEST_F(NearbyConnectionsManagerImplTest, ClearIncomingPayloads) {
// Begin: NearbyConnectionsManagerImplTestMediums
/******************************************************************************/
using MediumsTestParam =
std::tuple<PowerLevel, DataUsage, ConnectivityManager::ConnectionType, bool,
bool>;
std::tuple<PowerLevel, DataUsage, /*is_webrtc_enabled=*/bool,
/*is_wifilan_enabled=*/bool, /*is_lan_connected=*/bool,
/*is_internet_connected=*/bool>;
class NearbyConnectionsManagerImplTestMediums
: public NearbyConnectionsManagerImplTest,
public testing::WithParamInterface<MediumsTestParam> {};
@@ -1612,9 +1608,16 @@ TEST_P(NearbyConnectionsManagerImplTestMediums, StartAdvertising_Options) {
const MediumsTestParam& param = GetParam();
PowerLevel power_level = std::get<0>(param);
DataUsage data_usage = std::get<1>(param);
ConnectivityManager::ConnectionType connection_type = std::get<2>(param);
bool is_webrtc_enabled = std::get<3>(GetParam());
bool is_wifilan_enabled = std::get<4>(GetParam());
bool is_webrtc_enabled = std::get<2>(GetParam());
bool is_wifilan_enabled = std::get<3>(GetParam());
bool is_lan_connected = std::get<4>(GetParam());
bool is_internet_connected = std::get<5>(GetParam());
LOG(INFO) << "Test params: power_level: " << static_cast<int>(power_level)
<< ", data_usage: " << static_cast<int>(data_usage)
<< ", is_webrtc_enabled: " << is_webrtc_enabled
<< ", is_wifilan_enabled: " << is_wifilan_enabled
<< ", is_lan_connected: " << is_lan_connected
<< ", is_internet_connected: " << is_internet_connected;
if (is_webrtc_enabled) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
@@ -1634,19 +1637,13 @@ TEST_P(NearbyConnectionsManagerImplTestMediums, StartAdvertising_Options) {
config_package_nearby::nearby_sharing_feature::kEnableMediumWifiLan,
false);
}
SetConnectionType(connection_type);
SetConnectionStatus(is_lan_connected, is_internet_connected);
bool should_use_internet =
data_usage != DataUsage::OFFLINE_DATA_USAGE &&
connection_type != ConnectivityManager::ConnectionType::kNone &&
!(data_usage == DataUsage::WIFI_ONLY_DATA_USAGE &&
connection_type != ConnectivityManager::ConnectionType::kWifi);
bool is_connection_wifi_or_ethernet =
connection_type == ConnectivityManager::ConnectionType::kWifi ||
connection_type == ConnectivityManager::ConnectionType::kEthernet;
is_internet_connected && data_usage != DataUsage::OFFLINE_DATA_USAGE &&
!(data_usage == DataUsage::WIFI_ONLY_DATA_USAGE && !is_lan_connected);
should_use_web_rtc_ = is_webrtc_enabled && should_use_internet;
should_use_wifilan_ = is_wifilan_enabled & is_connection_wifi_or_ethernet;
should_use_wifilan_ = is_wifilan_enabled && is_lan_connected;
bool is_high_power = power_level == PowerLevel::kHighPower;
@@ -1706,10 +1703,8 @@ INSTANTIATE_TEST_SUITE_P(
testing::Values(DataUsage::WIFI_ONLY_DATA_USAGE,
DataUsage::OFFLINE_DATA_USAGE,
DataUsage::ONLINE_DATA_USAGE),
testing::Values(ConnectivityManager::ConnectionType::kNone,
ConnectivityManager::ConnectionType::kWifi,
ConnectivityManager::ConnectionType::k3G),
testing::Bool(), testing::Bool()));
testing::Bool(), testing::Bool(), testing::Bool(),
testing::Bool()));
/******************************************************************************/
// End: NearbyConnectionsManagerImplTestMediums
@@ -1867,8 +1862,8 @@ TEST_F(NearbyConnectionsManagerImplTest,
incoming_connection_listener,
payload_listener_remote) != nullptr);
FilePath file = Files::GetTemporaryDirectory().append(FilePath("file.jpg"));
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId, InputFile(file.ToString())));
payload_listener_remote.payload_cb(kRemoteEndpointId,
Payload(kPayloadId, file));
nearby_connections_manager_->OnPayloadTransferUpdateForTesting(
kRemoteEndpointId,
@@ -1900,8 +1895,8 @@ TEST_F(NearbyConnectionsManagerImplTest, OnPayloadReceivedForUnknownFile) {
incoming_connection_listener,
payload_listener_remote) != nullptr);
FilePath file = Files::GetTemporaryDirectory().append(FilePath("file.jpg"));
payload_listener_remote.payload_cb(
kRemoteEndpointId, Payload(kPayloadId, InputFile(file.ToString())));
payload_listener_remote.payload_cb(kRemoteEndpointId,
Payload(kPayloadId, file));
// Flag is on. Add unknown file paths with kCanceled to the list.
NearbyFlags::GetInstance().OverrideBoolFlagValue(
@@ -1909,12 +1904,12 @@ TEST_F(NearbyConnectionsManagerImplTest, OnPayloadReceivedForUnknownFile) {
kDeleteUnexpectedReceivedFileFix,
true);
nearby_connections_manager_->ClearIncomingPayloads();
Payload payload(kPayloadId, InputFile(file.ToString()));
Payload payload(kPayloadId, file);
nearby_connections_manager_->OnPayloadReceivedForTesting(kRemoteEndpointId,
payload);
FilePath file2 = Files::GetTemporaryDirectory().append(FilePath("file2.jpg"));
Payload payload2(kPayloadId, InputFile(file2.ToString()));
Payload payload2(kPayloadId, file2);
nearby_connections_manager_->OnPayloadReceivedForTesting(kRemoteEndpointId,
payload2);
auto unknown_file_paths =
@@ -1927,7 +1922,7 @@ TEST_F(NearbyConnectionsManagerImplTest, OnPayloadReceivedForUnknownFile) {
nearby_connections_manager_->RegisterPayloadStatusListener(
kPayloadId, payload_listener->GetWeakPtr());
FilePath file3 = Files::GetTemporaryDirectory().append(FilePath("file3.jpg"));
Payload payload3(kPayloadId, InputFile(file3.ToString()));
Payload payload3(kPayloadId, file3);
nearby_connections_manager_->OnPayloadReceivedForTesting(kRemoteEndpointId,
payload3);
unknown_file_paths =
@@ -1959,7 +1954,7 @@ TEST_F(NearbyConnectionsManagerImplTest,
FilePath file = Files::GetTemporaryDirectory().append(FilePath("file.jpg"));
Payload payload(kPayloadId, InputFile(file.ToString()));
Payload payload(kPayloadId, file);
nearby_connections_manager_->OnPayloadReceivedForTesting(kRemoteEndpointId,
payload);
@@ -1989,7 +1984,7 @@ TEST_F(NearbyConnectionsManagerImplTest,
});
FilePath file2 = Files::GetTemporaryDirectory().append(FilePath("file2.jpg"));
Payload payload2(kPayloadId, InputFile(file2.ToString()));
Payload payload2(kPayloadId, file2);
nearby_connections_manager_->OnPayloadReceivedForTesting(kRemoteEndpointId,
payload2);
unknown_file_paths =
+24 -11
View File
@@ -21,6 +21,13 @@
#include <utility>
#include <vector>
#include "connections/listeners.h"
#include "connections/payload.h"
#include "connections/payload_type.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/base/file_path.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/file.h"
#include "sharing/internal/public/logging.h"
#include "sharing/nearby_connections_types.h"
@@ -28,24 +35,31 @@
namespace nearby {
namespace sharing {
using ::nearby::connections::PayloadType;
using ::nearby::connections::ResultCallback;
using NcPayload = ::nearby::connections::Payload;
using NcStatus = ::nearby::connections::Status;
using NcStrategy = ::nearby::connections::Strategy;
Status ConvertToStatus(NcStatus status) {
return static_cast<Status>(status.value);
}
Payload ConvertToPayload(NcPayload payload) {
switch (payload.GetType()) {
case NcPayloadType::kBytes: {
const NcByteArray& bytes = payload.AsBytes();
case PayloadType::kBytes: {
const ByteArray& bytes = payload.AsBytes();
std::string data = std::string(bytes);
return Payload(payload.GetId(),
std::vector<uint8_t>(data.begin(), data.end()));
}
case NcPayloadType::kFile: {
case PayloadType::kFile: {
std::string file_path = payload.AsFile()->GetFilePath();
std::string parent_folder = payload.GetParentFolder();
VLOG(1) << __func__ << ": Payload file_path=" << file_path
<< ", parent_folder = " << parent_folder;
return Payload(payload.GetId(), InputFile(file_path), parent_folder);
return Payload(payload.GetId(), FilePath(file_path), parent_folder);
}
default:
return Payload();
@@ -55,15 +69,14 @@ Payload ConvertToPayload(NcPayload payload) {
NcPayload ConvertToServicePayload(Payload payload) {
switch (payload.content.type) {
case PayloadContent::Type::kFile: {
int64_t file_size = payload.content.file_payload.size;
std::string file_path = payload.content.file_payload.file.path.ToString();
std::string file_path = payload.content.file_payload.file_path.ToString();
std::string file_name =
payload.content.file_payload.file.path.GetFileName().ToString();
payload.content.file_payload.file_path.GetFileName().ToString();
std::string parent_folder = payload.content.file_payload.parent_folder;
std::replace(parent_folder.begin(), parent_folder.end(), '\\', '/');
VLOG(1) << __func__ << ": NC Payload file_path=" << file_path
<< ", parent_folder = " << parent_folder;
nearby::InputFile input_file(file_path, file_size);
nearby::InputFile input_file(file_path);
NcPayload nc_payload(payload.id, parent_folder, file_name,
std::move(input_file));
return nc_payload;
@@ -71,16 +84,16 @@ NcPayload ConvertToServicePayload(Payload payload) {
case PayloadContent::Type::kBytes: {
std::vector<uint8_t> bytes = payload.content.bytes_payload.bytes;
return NcPayload(payload.id,
NcByteArray(std::string(bytes.begin(), bytes.end())));
ByteArray(std::string(bytes.begin(), bytes.end())));
}
default:
return NcPayload();
}
}
NcResultCallback BuildResultCallback(
ResultCallback BuildResultCallback(
std::function<void(Status status)> callback) {
return NcResultCallback{[&, callback = std::move(callback)](NcStatus status) {
return ResultCallback{[&, callback = std::move(callback)](NcStatus status) {
callback(ConvertToStatus(status));
}};
}
+5 -36
View File
@@ -24,17 +24,8 @@
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "connections/advertising_options.h"
#include "connections/connection_options.h"
#include "connections/core.h"
#include "connections/discovery_options.h"
#include "connections/implementation/service_controller_router.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/params.h"
#include "connections/payload.h"
#include "connections/payload_type.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/platform/listeners.h"
@@ -43,27 +34,6 @@
namespace nearby {
namespace sharing {
using Core = ::nearby::connections::Core;
using ServiceControllerRouter = ::nearby::connections::ServiceControllerRouter;
using NcAdvertisingOptions = ::nearby::connections::AdvertisingOptions;
using NcByteArray = ::nearby::ByteArray;
using NcConnectionOptions = ::nearby::connections::ConnectionOptions;
using NcConnectionRequestInfo = ::nearby::connections::ConnectionRequestInfo;
using NcConnectionResponseInfo = ::nearby::connections::ConnectionResponseInfo;
using NcDistanceInfo = ::nearby::connections::DistanceInfo;
using NcDiscoveryListener = ::nearby::connections::DiscoveryListener;
using NcDiscoveryOptions = ::nearby::connections::DiscoveryOptions;
using NcMedium = ::nearby::connections::Medium;
using NcOutOfBandConnectionMetadata =
::nearby::connections::OutOfBandConnectionMetadata;
using NcPayload = ::nearby::connections::Payload;
using NcPayloadType = ::nearby::connections::PayloadType;
using NcPayloadListener = ::nearby::connections::PayloadListener;
using NcPayloadProgressInfo = ::nearby::connections::PayloadProgressInfo;
using NcResultCallback = ::nearby::connections::ResultCallback;
using NcStatus = ::nearby::connections::Status;
using NcStrategy = ::nearby::connections::Strategy;
// Main interface to control the NearbyConnections library. Implemented in a
// sandboxed process. This interface is used by the browser process to connect
// to remote devices and send / receive raw data packets. Parsing of those
@@ -71,7 +41,6 @@ using NcStrategy = ::nearby::connections::Strategy;
// separate interface.
class NearbyConnectionsService {
public:
using HANDLE = void*;
virtual ~NearbyConnectionsService() = default;
struct ConnectionListener {
@@ -171,12 +140,12 @@ class NearbyConnectionsService {
virtual std::string Dump() const = 0;
};
Status ConvertToStatus(NcStatus status);
Payload ConvertToPayload(NcPayload payload);
NcPayload ConvertToServicePayload(Payload payload);
NcResultCallback BuildResultCallback(
Status ConvertToStatus(nearby::connections::Status status);
Payload ConvertToPayload(nearby::connections::Payload payload);
nearby::connections::Payload ConvertToServicePayload(Payload payload);
nearby::connections::ResultCallback BuildResultCallback(
std::function<void(Status status)> callback);
NcStrategy ConvertToServiceStrategy(Strategy strategy);
nearby::connections::Strategy ConvertToServiceStrategy(Strategy strategy);
} // namespace sharing
} // namespace nearby
+38 -11
View File
@@ -27,10 +27,20 @@
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "connections/advertising_options.h"
#include "connections/connection_options.h"
#include "connections/core.h"
#include "connections/discovery_options.h"
#include "connections/implementation/service_controller_router.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/params.h"
#include "connections/payload.h"
#include "connections/payload_type.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/analytics/event_logger.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/logging.h"
#include "internal/platform/mac_address.h"
#include "sharing/internal/public/connectivity_manager.h"
@@ -41,7 +51,24 @@ namespace nearby {
namespace sharing {
namespace {
Core* GetService(NearbyConnectionsService::HANDLE handle) {
using ::nearby::connections::ConnectionRequestInfo;
using ::nearby::connections::ConnectionResponseInfo;
using ::nearby::connections::Core;
using ::nearby::connections::PayloadProgressInfo;
using ::nearby::connections::PayloadType;
using ::nearby::connections::ServiceControllerRouter;
using NcAdvertisingOptions = ::nearby::connections::AdvertisingOptions;
using NcConnectionOptions = ::nearby::connections::ConnectionOptions;
using NcDiscoveryListener = ::nearby::connections::DiscoveryListener;
using NcDiscoveryOptions = ::nearby::connections::DiscoveryOptions;
using NcDistanceInfo = ::nearby::connections::DistanceInfo;
using NcMedium = ::nearby::connections::Medium;
using NcPayload = ::nearby::connections::Payload;
using NcPayloadListener = ::nearby::connections::PayloadListener;
using NcStatus = ::nearby::connections::Status;
Core* GetService(NearbyConnectionsServiceImpl::HANDLE handle) {
return reinterpret_cast<Core*>(handle);
}
@@ -88,12 +115,12 @@ void NearbyConnectionsServiceImpl::StartAdvertising(
options.fast_advertisement_service_uuid =
advertising_options.fast_advertisement_service_uuid.uuid;
NcConnectionRequestInfo connection_request_info;
ConnectionRequestInfo connection_request_info;
connection_request_info.endpoint_info =
NcByteArray(std::string(endpoint_info.begin(), endpoint_info.end()));
ByteArray(std::string(endpoint_info.begin(), endpoint_info.end()));
connection_request_info.listener.initiated_cb =
[&](const std::string& endpoint_id,
const NcConnectionResponseInfo& info) {
const ConnectionResponseInfo& info) {
ConnectionInfo connection_info;
connection_info.authentication_token = info.authentication_token;
std::string remote_end_point = std::string(info.remote_endpoint_info);
@@ -166,7 +193,7 @@ void NearbyConnectionsServiceImpl::StartDiscovery(
NcDiscoveryListener listener;
listener.endpoint_found_cb = [this](const std::string& endpoint_id,
const NcByteArray& endpoint_info,
const ByteArray& endpoint_info,
const std::string& service_id) {
std::string endpoint_info_data = std::string(endpoint_info);
discovery_listener_.endpoint_found_cb(
@@ -224,12 +251,12 @@ void NearbyConnectionsServiceImpl::RequestConnection(
}
options.non_disruptive_hotspot_mode =
connection_options.non_disruptive_hotspot_mode;
NcConnectionRequestInfo connection_request_info;
ConnectionRequestInfo connection_request_info;
connection_request_info.endpoint_info =
NcByteArray(std::string(endpoint_info.begin(), endpoint_info.end()));
ByteArray(std::string(endpoint_info.begin(), endpoint_info.end()));
connection_request_info.listener.initiated_cb =
[&](const std::string& endpoint_id,
const NcConnectionResponseInfo& info) {
const ConnectionResponseInfo& info) {
ConnectionInfo connection_info;
connection_info.authentication_token = info.authentication_token;
std::string remote_end_point = std::string(info.remote_endpoint_info);
@@ -312,8 +339,8 @@ void NearbyConnectionsServiceImpl::AcceptConnection(
VLOG(1) << "payload callback id=" << payload.GetId();
switch (payload.GetType()) {
case NcPayloadType::kBytes:
case NcPayloadType::kFile:
case PayloadType::kBytes:
case PayloadType::kFile:
payload_listener->second.payload_cb(
endpoint_id, ConvertToPayload(std::move(payload)));
break;
@@ -324,7 +351,7 @@ void NearbyConnectionsServiceImpl::AcceptConnection(
},
.payload_progress_cb =
[&](absl::string_view endpoint_id,
const NcPayloadProgressInfo& info) {
const PayloadProgressInfo& info) {
PayloadTransferUpdate transfer_update;
transfer_update.bytes_transferred = info.bytes_transferred;
transfer_update.payload_id = info.payload_id;
@@ -35,6 +35,8 @@ namespace sharing {
class NearbyConnectionsServiceImpl : public NearbyConnectionsService {
public:
using HANDLE = void*;
explicit NearbyConnectionsServiceImpl(
nearby::ConnectivityManager* connectivity_manager,
nearby::analytics::EventLogger* event_logger = nullptr);
+6 -2
View File
@@ -17,6 +17,8 @@
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "connections/payload.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/file.h"
#include "sharing/nearby_connections_types.h"
@@ -25,15 +27,17 @@ namespace {
using ::testing::Eq;
using NcPayload = ::nearby::connections::Payload;
TEST(NearbyConnectionSharingServicePayloadTest, ConvertBytesToPayload) {
Payload payload = ConvertToPayload(NcPayload(1234, NcByteArray("test")));
Payload payload = ConvertToPayload(NcPayload(1234, ByteArray("test")));
EXPECT_THAT(payload.id, Eq(1234LL));
EXPECT_THAT(payload.content.type, Eq(PayloadContent::Type::kBytes));
}
TEST(NearbyConnectionSharingServicePayloadTest, ConvertFileToPayload) {
Payload payload = ConvertToPayload(
NcPayload(1234, nearby::InputFile("/为甚么/tmp/test.txt", /*size=*/100)));
NcPayload(1234, nearby::InputFile("/为甚么/tmp/test.txt")));
EXPECT_THAT(payload.id, Eq(1234LL));
EXPECT_THAT(payload.content.type, Eq(PayloadContent::Type::kFile));
}
+7 -31
View File
@@ -28,7 +28,6 @@
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/interop/authentication_status.h"
namespace nearby {
@@ -357,14 +356,6 @@ enum class DistanceInfo {
kFar = 4,
};
struct InputFile {
InputFile() = default;
explicit InputFile(absl::string_view file_path)
: path(file_path) {}
FilePath path;
};
// A simple payload containing raw bytes.
struct BytesPayload {
// The bytes of this payload.
@@ -376,8 +367,7 @@ struct FilePayload {
// The file to which this payload points to. When sending this payload, the
// NearbyConnections library reads from this file. When receiving a file
// payload it writes to this file.
InputFile file;
int64_t size;
FilePath file_path;
std::string parent_folder;
};
@@ -410,35 +400,21 @@ struct Payload {
explicit Payload(std::vector<uint8_t> bytes)
: Payload(GenerateId(), std::move(bytes)) {}
explicit Payload(InputFile file,
absl::string_view parent_folder = absl::string_view()) {
id = std::hash<std::string>()(file.path.ToString());
content.type = PayloadContent::Type::kFile;
std::optional<uintmax_t> size = Files::GetFileSize(file.path);
if (size.has_value()) {
content.file_payload.size = *size;
}
content.file_payload.file = std::move(file);
content.file_payload.parent_folder = std::string(parent_folder);
}
explicit Payload(FilePath file_path,
absl::string_view parent_folder = absl::string_view())
: Payload(std::hash<std::string>()(file_path.ToString()), file_path,
parent_folder) {}
Payload(int64_t id, std::vector<uint8_t> bytes) : id(id) {
content.type = PayloadContent::Type::kBytes;
content.bytes_payload.bytes = std::move(bytes);
}
Payload(int64_t id, InputFile file,
Payload(int64_t id, FilePath file_path,
absl::string_view parent_folder = absl::string_view())
: id(id) {
content.type = PayloadContent::Type::kFile;
std::optional<uintmax_t> size = Files::GetFileSize(file.path);
if (size.has_value()) {
content.file_payload.size = *size;
}
content.file_payload.file = std::move(file);
content.file_payload.file_path = file_path;
content.file_payload.parent_folder = std::string(parent_folder);
}
@@ -21,20 +21,6 @@
namespace nearby::sharing {
using ::testing::Eq;
TEST(NearbyConnectionSharingTypesPayloadTest, FromInputFileUTF8) {
InputFile input_file("/为甚么/tmp/test.txt");
Payload payload(input_file);
EXPECT_THAT(payload.id, Eq(7724502655048749887LL));
EXPECT_THAT(payload.content.type, Eq(PayloadContent::Type::kFile));
}
TEST(NearbyConnectionSharingTypesPayloadTest, FromInputFileWithId) {
InputFile input_file("/为甚么/tmp/test.txt");
Payload payload(1234, input_file);
EXPECT_THAT(payload.id, Eq(1234LL));
EXPECT_THAT(payload.content.type, Eq(PayloadContent::Type::kFile));
}
TEST(NearbyConnectionSharingTypesPayloadTest, FromBytes) {
Payload payload({1, 2, 3, 4, 5});
EXPECT_THAT(payload.content.type, Eq(PayloadContent::Type::kBytes));
-25
View File
@@ -38,22 +38,6 @@ namespace {
using ::nearby::sharing::api::SharingPlatform;
// Called on the FileTaskRunner to actually open the files passed.
std::vector<NearbyFileHandler::FileInfo> DoOpenFiles(
absl::Span<const FilePath> file_paths) {
std::vector<NearbyFileHandler::FileInfo> files;
for (const auto& file_path : file_paths) {
std::optional<uintmax_t> size = Files::GetFileSize(file_path);
if (!size.has_value()) {
LOG(ERROR) << __func__
<< ": Failed to open file. File=" << file_path.ToString();
return {};
}
files.push_back({*size, file_path});
}
return files;
}
} // namespace
NearbyFileHandler::NearbyFileHandler(SharingPlatform& platform,
@@ -68,15 +52,6 @@ NearbyFileHandler::NearbyFileHandler(SharingPlatform& platform,
NearbyFileHandler::~NearbyFileHandler() = default;
void NearbyFileHandler::OpenFiles(std::vector<FilePath> file_paths,
OpenFilesCallback callback) {
sequenced_task_runner_->PostTask(
[callback = std::move(callback), file_paths = std::move(file_paths)]() {
auto opened_files = DoOpenFiles(file_paths);
callback(opened_files);
});
}
void NearbyFileHandler::DeleteFilesFromDisk(
std::vector<FilePath> file_paths, DeleteFilesFromDiskCallback callback) {
sequenced_task_runner_->PostTask([callback = std::move(callback),
-10
View File
@@ -33,12 +33,6 @@ namespace sharing {
// releasing files need to run on a MayBlock task runner.
class NearbyFileHandler {
public:
struct FileInfo {
uint64_t size;
FilePath file_path;
};
using OpenFilesCallback = std::function<void(std::vector<FileInfo>)>;
using DeleteFilesFromDiskCallback = std::function<void()>;
// Pass in a TaskRunner to use for testing.
@@ -46,10 +40,6 @@ class NearbyFileHandler {
std::unique_ptr<TaskRunner> runner = nullptr);
~NearbyFileHandler();
// Open the files given in |file_paths| and return the opened files sizes via
// |callback|. If any file fails to open, return an empty list.
void OpenFiles(std::vector<FilePath> file_paths, OpenFilesCallback callback);
void DeleteFilesFromDisk(std::vector<FilePath> file_paths,
DeleteFilesFromDiskCallback callback);
-22
View File
@@ -22,7 +22,6 @@
#include <vector>
#include "gtest/gtest.h"
#include "absl/synchronization/notification.h"
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
@@ -46,27 +45,6 @@ bool CreateFile(FilePath& file_path) {
return true;
}
TEST(NearbyFileHandler, OpenFiles) {
MockSharingPlatform mock_platform;
NearbyFileHandler nearby_file_handler(mock_platform);
absl::Notification notification;
std::vector<NearbyFileHandler::FileInfo> result;
FilePath test_file = Files::GetTemporaryDirectory().append(
FilePath("nearby_nfh_test_abc.jpg"));
ASSERT_TRUE(CreateFile(test_file));
nearby_file_handler.OpenFiles(
{test_file}, [&result, &notification](
std::vector<NearbyFileHandler::FileInfo> file_infos) {
result = file_infos;
notification.Notify();
});
notification.WaitForNotificationWithTimeout(absl::Seconds(1));
EXPECT_EQ(result.size(), 1);
ASSERT_TRUE(Files::RemoveFile(test_file));
}
TEST(NearbyFileHandler, DeleteAFileFromDisk) {
MockSharingPlatform mock_platform;
FakeClock clock;
+12 -2
View File
@@ -14,13 +14,13 @@
#include "sharing/nearby_sharing_service_factory.h"
#include <cstdint>
#include <memory>
#include <utility>
#include "internal/analytics/event_logger.h"
#include "internal/platform/task_runner.h"
#include "sharing/analytics/analytics_recorder.h"
#include "sharing/contacts/nearby_share_contact_manager_impl.h"
#include "sharing/internal/api/sharing_platform.h"
#include "sharing/internal/public/context_impl.h"
#include "sharing/nearby_connections_manager_factory.h"
@@ -54,9 +54,19 @@ NearbySharingService* NearbySharingServiceFactory::CreateSharingService(
service_thread.get(), context_.get(),
sharing_platform.GetDeviceInfo(), event_logger);
auto nearby_share_client_factory =
sharing_platform.CreateSharingRpcClientFactory(context_->GetClock(),
analytics_recorder);
auto nearby_share_contact_manager =
std::make_unique<NearbyShareContactManagerImpl>(
context_.get(), sharing_platform.GetAccountManager(),
nearby_share_client_factory.get());
nearby_sharing_service_ = std::make_unique<NearbySharingServiceImpl>(
std::move(service_thread), context_.get(), sharing_platform,
std::move(nearby_connections_manager), analytics_recorder);
std::move(nearby_share_client_factory),
std::move(nearby_connections_manager),
std::move(nearby_share_contact_manager), analytics_recorder);
return nearby_sharing_service_.get();
}
+143 -343
View File
@@ -63,7 +63,6 @@
#include "sharing/common/nearby_share_prefs.h"
#include "sharing/constants.h"
#include "sharing/contacts/nearby_share_contact_manager.h"
#include "sharing/contacts/nearby_share_contact_manager_impl.h"
#include "sharing/fast_initiation/nearby_fast_initiation.h"
#include "sharing/fast_initiation/nearby_fast_initiation_impl.h"
#include "sharing/file_attachment.h"
@@ -72,6 +71,7 @@
#include "sharing/incoming_share_session.h"
#include "sharing/internal/api/bluetooth_adapter.h"
#include "sharing/internal/api/sharing_platform.h"
#include "sharing/internal/api/sharing_rpc_client.h"
#include "sharing/internal/base/encode.h"
#include "sharing/internal/public/connectivity_manager.h"
#include "sharing/internal/public/context.h"
@@ -107,10 +107,12 @@ 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;
using ::nearby::sharing::api::SharingPlatform;
using ::nearby::sharing::api::SharingRpcClientFactory;
using ::nearby::sharing::proto::DataUsage;
using ::nearby::sharing::proto::DeviceVisibility;
using ::nearby::sharing::service::proto::ConnectionResponseFrame;
@@ -127,10 +129,6 @@ constexpr absl::Duration kProcessShutdownPendingTimerDelay = // NOLINT
absl::Seconds(15);
constexpr absl::Duration kProcessNetworkChangeTimerDelay = absl::Seconds(1);
// Cooldown period after a successful incoming share before we allow the "Device
// nearby is sharing" notification to appear again.
constexpr absl::Duration kFastInitiationScannerCooldown = absl::Seconds(8);
// The maximum number of certificate downloads that can be performed during a
// discovery session.
// Assuming a 2min discovery session and 10s download interval.
@@ -206,12 +204,38 @@ std::string GenerateDeviceId() {
return id;
}
std::string ReceiveSurfaceStateToString(
NearbySharingService::ReceiveSurfaceState state) {
switch (state) {
case NearbySharingService::ReceiveSurfaceState::kForeground:
return "FOREGROUND";
case NearbySharingService::ReceiveSurfaceState::kBackground:
return "BACKGROUND";
case NearbySharingService::ReceiveSurfaceState::kUnknown:
return "UNKNOWN";
}
}
std::string SendSurfaceStateToString(
NearbySharingService::SendSurfaceState state) {
switch (state) {
case NearbySharingService::SendSurfaceState::kForeground:
return "FOREGROUND";
case NearbySharingService::SendSurfaceState::kBackground:
return "BACKGROUND";
case NearbySharingService::SendSurfaceState::kUnknown:
return "UNKNOWN";
}
}
} // namespace
NearbySharingServiceImpl::NearbySharingServiceImpl(
std::unique_ptr<TaskRunner> service_thread, Context* context,
SharingPlatform& sharing_platform,
std::unique_ptr<SharingRpcClientFactory> nearby_share_client_factory,
std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager,
std::unique_ptr<NearbyShareContactManager> contact_manager,
analytics::AnalyticsRecorder* analytics_recorder)
: service_thread_(std::move(service_thread)),
context_(context),
@@ -220,14 +244,11 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
account_manager_(sharing_platform.GetAccountManager()),
analytics_recorder_(*analytics_recorder),
nearby_connections_manager_(std::move(nearby_connections_manager)),
nearby_share_client_factory_(
sharing_platform.CreateSharingRpcClientFactory(context_->GetClock(),
&analytics_recorder_)),
nearby_share_client_factory_(std::move(nearby_share_client_factory)),
local_device_data_manager_(
NearbyShareLocalDeviceDataManagerImpl::Factory::Create(
preference_manager_, account_manager_, device_info_)),
contact_manager_(NearbyShareContactManagerImpl::Factory::Create(
context_, account_manager_, nearby_share_client_factory_.get())),
contact_manager_(std::move(contact_manager)),
nearby_fast_initiation_(
NearbyFastInitiationImpl::Factory::Create(context_)),
settings_(std::make_unique<NearbyShareSettings>(
@@ -239,9 +260,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);
@@ -255,11 +280,8 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
profile_path, nearby_share_client_factory_.get()),
certificate_manager_->AddObserver(this);
context_->GetConnectivityManager()->RegisterConnectionListener(
kConnectionListenerName,
[this](nearby::ConnectivityManager::ConnectionType type,
bool is_lan_connected, bool is_internet_connected) {
OnNetworkChanged(type);
context_->GetConnectivityManager()->RegisterLanListener(
kConnectionListenerName, [this](bool is_lan_connected) {
OnLanConnectedChanged(is_lan_connected);
});
@@ -299,7 +321,6 @@ void NearbySharingServiceImpl::Shutdown(
service_observers_.Clear();
StopAdvertising();
StopFastInitiationScanning();
StopFastInitiationAdvertising();
StopScanning();
nearby_connections_manager_->Shutdown();
@@ -308,7 +329,7 @@ void NearbySharingServiceImpl::Shutdown(
certificate_manager_->RemoveObserver(this);
account_manager_.RemoveObserver(this);
context_->GetConnectivityManager()->UnregisterConnectionListener(
context_->GetConnectivityManager()->UnregisterLanListener(
kConnectionListenerName);
context_->GetBluetoothAdapter().RemoveObserver(this);
nearby_fast_initiation_->RemoveObserver(this);
@@ -482,7 +503,7 @@ void NearbySharingServiceImpl::RegisterSendSurface(
// request comes from a surface with the blocked vendor ID.
wrapped_callback.OnShareTargetDiscovered(share_target);
transfer_callback->OnTransferUpdate(
share_target, attachment_container, transfer_metadata);
share_target, *attachment_container, transfer_metadata);
}
// Sync down data from Nearby server when the sending flow starts,
@@ -594,7 +615,7 @@ void NearbySharingServiceImpl::RegisterReceiveSurface(
auto& [share_target, attachment_container, transfer_metadata] =
*last_incoming_metadata_;
transfer_callback->OnTransferUpdate(
share_target, attachment_container, transfer_metadata);
share_target, *attachment_container, transfer_metadata);
}
GetReceiveCallbacksMapFromState(state).insert(
@@ -716,7 +737,7 @@ void NearbySharingServiceImpl::SendAttachments(
CreateEndpointInfo(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS,
local_device_data_manager_->GetDeviceName());
if (!endpoint_info) {
LOG(WARNING) << "Could not create local endpoint info.";
LOG(WARNING) << "Could not create local endpoint info.";
std::move(status_codes_callback)(StatusCodes::kError);
return;
}
@@ -729,31 +750,30 @@ void NearbySharingServiceImpl::SendAttachments(
return;
}
session->InitiateSendAttachments(std::move(attachment_container));
app_info_->SetActiveFlag();
OnTransferStarted(/*is_incoming=*/false);
is_connecting_ = true;
InvalidateSendSurfaceState();
// Send process initialized successfully, from now on status updated
// will be sent out via OnOutgoingTransferUpdate().
session->UpdateTransferMetadata(
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kConnecting)
.build());
CreatePayloads(
*session, [this, endpoint_info = std::move(*endpoint_info)](
OutgoingShareSession& session, bool success) {
OnCreatePayloads(std::move(endpoint_info), session, success);
});
if (session->InitiateSendAttachments(
std::move(attachment_container))) {
OutgoingSessionConnect(*session, std::move(*endpoint_info));
}
std::move(status_codes_callback)(StatusCodes::kOk);
});
}
void NearbySharingServiceImpl::OutgoingSessionConnect(
OutgoingShareSession& session, std::vector<uint8_t> endpoint_info) {
OnTransferStarted(/*is_incoming=*/false);
is_connecting_ = true;
InvalidateSendSurfaceState();
int64_t share_target_id = session.share_target().id;
session.Connect(
std::move(endpoint_info), settings_->GetDataUsage(),
GetDisableWifiHotspotState(),
absl::bind_front(&NearbySharingServiceImpl::OnOutgoingConnection, this,
share_target_id));
}
bool NearbySharingServiceImpl::OutgoingSessionAccept(
OutgoingShareSession& session) {
return session.AcceptTransfer(
@@ -1040,15 +1060,23 @@ NearbySharingServiceImpl::InternalUnregisterSendSurface(
*last_outgoing_metadata_;
for (auto& background_transfer_callback : background_send_surface_map_) {
background_transfer_callback.first->OnTransferUpdate(
share_target, attachment_container, transfer_metadata);
share_target, *attachment_container, transfer_metadata);
}
}
if (foreground_send_surface_map_.empty() &&
background_send_surface_map_.empty()) {
LOG(INFO) << __func__ << ": Last send surface has been unregistered";
// Clear outgoing_share_targets, outgoing_share_sessions and
// discovery_cache.
outgoing_targets_manager_.Cleanup();
if (foreground_send_surface_map_.empty()) {
if (background_send_surface_map_.empty()) {
LOG(INFO) << __func__ << ": Last send surface has been unregistered";
// Clear outgoing_share_targets, outgoing_share_sessions and
// discovery_cache.
outgoing_targets_manager_.Cleanup();
} else {
LOG(INFO) << __func__
<< ": All foreground send surface has been unregistered";
outgoing_targets_manager_.AllTargetsLost(
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
config_package_nearby::nearby_sharing_feature::
kUnregisterTargetDiscoveryCacheLostExpiryMs)));
}
}
VLOG(1) << __func__ << ": A SendSurface has been unregistered: "
@@ -1098,7 +1126,7 @@ NearbySharingServiceImpl::InternalUnregisterReceiveSurface(
*last_incoming_metadata_;
for (auto& background_callback : background_receive_callbacks_map_) {
background_callback.first->OnTransferUpdate(
share_target, attachment_container, transfer_metadata);
share_target, *attachment_container, transfer_metadata);
}
}
@@ -1162,12 +1190,11 @@ std::string NearbySharingServiceImpl::Dump() const {
preference_manager_,
PrefNames::kSchedulerDownloadPublicCertificates)
<< std::endl;
sstream
<< " Upload local device certificates: "
<< ConvertToReadableSchedule(
preference_manager_,
PrefNames::kSchedulerUploadLocalDeviceCertificates)
<< std::endl;
sstream << " Upload local device certificates: "
<< ConvertToReadableSchedule(
preference_manager_,
PrefNames::kSchedulerUploadLocalDeviceCertificates)
<< std::endl;
sstream << " Private certificates expiration: "
<< ConvertToReadableSchedule(
preference_manager_,
@@ -1328,26 +1355,30 @@ void NearbySharingServiceImpl::OnLockStateChanged(bool locked) {
void NearbySharingServiceImpl::AdapterPresentChanged(
sharing::api::BluetoothAdapter* adapter, bool present) {
RunOnNearbySharingServiceThread(
"bt_adapter_present_changed", [this, adapter, present]() {
VLOG(1) << "Bluetooth adapter present state changed. (" << present
<< ")";
NearbySharingService::Observer::AdapterState state =
MapAdapterState(present, adapter->IsPowered());
service_observers_.NotifyBluetoothStatusChanged(state);
InvalidateSurfaceState();
});
RunOnNearbySharingServiceThread("bt_adapter_present_changed", [this, adapter,
present]() {
VLOG(1) << "Bluetooth adapter present state changed. (" << present << ")";
NearbySharingService::Observer::AdapterState state =
MapAdapterState(present, adapter->IsPowered());
service_observers_.NotifyBluetoothStatusChanged(state);
});
}
void NearbySharingServiceImpl::AdapterPoweredChanged(
sharing::api::BluetoothAdapter* adapter, bool powered) {
RunOnNearbySharingServiceThread(
"bt_adapter_power_changed", [this, adapter, powered]() {
// When adpater is powered on, it takes some time for the RFCOMM service to
// be ready. If we don't wait the RfCommServiceProvider::CreateAsync() call
// fails with a "device is not ready for use" error.
// Waiting 500ms seems to be enough to allow it to reliably work.
// Should investigate if there is a better events to listen to.
RunOnNearbySharingServiceThreadDelayed(
"bt_adapter_power_changed", absl::Milliseconds(500),
[this, adapter, powered]() {
VLOG(1) << "Bluetooth adapter power state changed. (" << powered << ")";
NearbySharingService::Observer::AdapterState state =
MapAdapterState(adapter->IsPresent(), powered);
service_observers_.NotifyBluetoothStatusChanged(state);
InvalidateSurfaceState();
StopAdvertisingAndInvalidateSurfaceState();
});
}
@@ -1608,10 +1639,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 +1735,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();
}
@@ -1807,14 +1794,9 @@ bool NearbySharingServiceImpl::HasAvailableConnectionMediums() {
bool is_wifi_lan_enabled = NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::kEnableMediumWifiLan);
ConnectivityManager::ConnectionType connection_type =
context_->GetConnectivityManager()->GetConnectionType();
bool hasNetworkConnection =
connection_type == ConnectivityManager::ConnectionType::kWifi ||
connection_type == ConnectivityManager::ConnectionType::kEthernet;
return IsBluetoothPowered() || (is_wifi_lan_enabled && hasNetworkConnection);
return IsBluetoothPowered() ||
(is_wifi_lan_enabled &&
context_->GetConnectivityManager()->IsLanConnected());
}
void NearbySharingServiceImpl::InvalidateSurfaceState() {
@@ -1905,7 +1887,6 @@ void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
InvalidateAdvertisingState();
InvalidateFastInitiationScanning();
}
void NearbySharingServiceImpl::InvalidateAdvertisingState() {
@@ -2006,8 +1987,7 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
*endpoint_info,
/*listener=*/this, power_level, data_usage,
visibility == DeviceVisibility::DEVICE_VISIBILITY_EVERYONE,
force_new_endpoint_id_,
[this, visibility, data_usage](Status status) {
force_new_endpoint_id_, [this, visibility, data_usage](Status status) {
// Log analytics event of advertising start.
analytics_recorder_.NewAdvertiseDevicePresenceStart(
advertising_session_id_, visibility,
@@ -2070,7 +2050,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::
kUnregisterTargetDiscoveryCacheLostExpiryMs)));
discovered_advertisements_to_retry_map_.clear();
discovered_advertisements_retried_set_.clear();
@@ -2131,102 +2114,6 @@ void NearbySharingServiceImpl::StopAdvertisingAndInvalidateSurfaceState() {
InvalidateSurfaceState();
}
void NearbySharingServiceImpl::InvalidateFastInitiationScanning() {
bool is_hardware_offloading_supported =
IsBluetoothPresent() && nearby_fast_initiation_->IsScanOffloadSupported();
// Hardware offloading support is computed when the bluetooth adapter becomes
// available. We set the hardware supported state on |settings_| to notify the
// UI of state changes. InvalidateFastInitiationScanning gets triggered on
// adapter change events.
settings_->SetIsFastInitiationHardwareSupported(
is_hardware_offloading_supported);
if (fast_initiation_scanner_cooldown_timer_ &&
fast_initiation_scanner_cooldown_timer_->IsRunning()) {
VLOG(1) << __func__
<< ": Stopping background scanning due to post-transfer "
"cooldown period";
StopFastInitiationScanning();
return;
}
// Screen is off. Do no work.
if (is_screen_locked_) {
VLOG(1) << __func__
<< ": Stopping background scanning because the screen is locked.";
StopFastInitiationScanning();
return;
}
if (!IsBluetoothPowered()) {
VLOG(1)
<< __func__
<< ": Stopping background scanning because bluetooth is powered down.";
StopFastInitiationScanning();
return;
}
// We're scanning for other nearby devices. Don't background scan.
if (is_scanning_) {
VLOG(1) << __func__
<< ": Stopping background scanning because we're scanning "
"for other devices.";
StopFastInitiationScanning();
return;
}
if (is_transferring_) {
VLOG(1) << __func__
<< ": Stopping background scanning because we're currently "
"in the midst of a transfer.";
StopFastInitiationScanning();
return;
}
if (advertising_power_level_ == PowerLevel::kHighPower) {
VLOG(1) << __func__
<< ": Stopping background scanning because we're already "
"in high visibility mode.";
StopFastInitiationScanning();
return;
}
if (!is_hardware_offloading_supported) {
VLOG(1) << __func__
<< ": Stopping background scanning because hardware "
"support is not available or not ready.";
StopFastInitiationScanning();
return;
}
StartFastInitiationScanning();
}
void NearbySharingServiceImpl::StartFastInitiationScanning() {
VLOG(1) << __func__ << ": Starting background scanning.";
if (nearby_fast_initiation_->IsScanning()) {
return;
}
nearby_fast_initiation_->StartScanning(
/*devices_discovered_callback=*/[]() {},
/*devices_not_discovered_callback=*/[]() {},
[this]() { StopFastInitiationScanning(); });
}
void NearbySharingServiceImpl::StopFastInitiationScanning() {
VLOG(1) << __func__ << ": Stop fast initiation scanning.";
if (!nearby_fast_initiation_->IsScanning()) {
return;
}
nearby_fast_initiation_->StopScanning(
[]() { VLOG(1) << __func__ << ": Stopped fast initiation scanning."; });
VLOG(1) << __func__ << ": Stopped background scanning.";
}
void NearbySharingServiceImpl::ScheduleRotateBackgroundAdvertisementTimer() {
absl::BitGen bitgen;
uint64_t delayMilliseconds = absl::Uniform(
@@ -2308,70 +2195,6 @@ void NearbySharingServiceImpl::OnOutgoingConnection(
}
}
void NearbySharingServiceImpl::CreatePayloads(
OutgoingShareSession& session,
std::function<void(OutgoingShareSession&, bool)> callback) {
int64_t share_target_id = session.share_target().id;
if (!session.file_payloads().empty() || !session.text_payloads().empty() ||
!session.wifi_credentials_payloads().empty()) {
// We may have already created the payloads in the case of retry, so we can
// skip this step.
std::move(callback)(session, /*success=*/false);
return;
}
session.CreateTextPayloads();
session.CreateWifiCredentialsPayloads();
file_handler_.OpenFiles(
session.GetFilePaths(),
[this, share_target_id, callback = std::move(callback)](
std::vector<NearbyFileHandler::FileInfo> file_infos) {
RunOnNearbySharingServiceThread(
"open_files",
[this, share_target_id, callback = std::move(callback),
file_infos = std::move(file_infos)]() {
OutgoingShareSession* session =
outgoing_targets_manager_.GetOutgoingShareSession(
share_target_id);
if (session == nullptr) {
return;
}
bool result = session->CreateFilePayloads(file_infos);
std::move(callback)(*session, result);
});
});
}
void NearbySharingServiceImpl::OnCreatePayloads(
std::vector<uint8_t> endpoint_info, OutgoingShareSession& session,
bool success) {
bool has_payloads = !session.text_payloads().empty() ||
!session.file_payloads().empty() ||
!session.wifi_credentials_payloads().empty();
if (!success || !has_payloads) {
LOG(WARNING) << __func__
<< ": Failed to send file to remote ShareTarget. Failed to "
"create payloads.";
session.UpdateTransferMetadata(
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kMediaUnavailable)
.build());
return;
}
// Log analytics event of describing attachments.
analytics_recorder_.NewDescribeAttachments(session.attachment_container());
std::optional<std::vector<uint8_t>> bluetooth_mac_address =
GetBluetoothMacAddressForShareTarget(session);
int64_t share_target_id = session.share_target().id;
session.Connect(
std::move(endpoint_info), std::move(bluetooth_mac_address),
settings_->GetDataUsage(), GetDisableWifiHotspotState(),
absl::bind_front(&NearbySharingServiceImpl::OnOutgoingConnection, this,
share_target_id));
}
void NearbySharingServiceImpl::Fail(IncomingShareSession& session,
TransferMetadata::Status status) {
RunOnNearbySharingServiceThreadDelayed(
@@ -2432,11 +2255,16 @@ void NearbySharingServiceImpl::OnIncomingTransferUpdate(
}
if (metadata.status() != TransferMetadata::Status::kCancelled &&
metadata.status() != TransferMetadata::Status::kRejected) {
last_incoming_metadata_ =
std::make_tuple(session.share_target(), session.attachment_container(),
TransferMetadataBuilder::Clone(metadata)
.set_is_original(false)
.build());
last_incoming_metadata_ = std::make_tuple(
session.share_target(),
AttachmentContainer::Builder(
session.attachment_container().GetTextAttachments(),
session.attachment_container().GetFileAttachments(),
session.attachment_container().GetWifiCredentialsAttachments())
.Build(),
TransferMetadataBuilder::Clone(metadata)
.set_is_original(false)
.build());
} else {
last_incoming_metadata_ = std::nullopt;
}
@@ -2524,11 +2352,16 @@ void NearbySharingServiceImpl::OnOutgoingTransferUpdate(
if (has_foreground_send_surface && metadata.is_final_status()) {
last_outgoing_metadata_ = std::nullopt;
} else {
last_outgoing_metadata_ =
std::make_tuple(session.share_target(), session.attachment_container(),
TransferMetadataBuilder::Clone(metadata)
.set_is_original(false)
.build());
last_outgoing_metadata_ = std::make_tuple(
session.share_target(),
AttachmentContainer::Builder(
session.attachment_container().GetTextAttachments(),
session.attachment_container().GetFileAttachments(),
session.attachment_container().GetWifiCredentialsAttachments())
.Build(),
TransferMetadataBuilder::Clone(metadata)
.set_is_original(false)
.build());
}
}
@@ -2646,20 +2479,12 @@ void NearbySharingServiceImpl::OnOutgoingConnectionKeyVerificationDone(
return;
}
// Auto Accept if key verification is successful or skip sender confirmation.
bool be_advanced_protection_enabled =
bool protection_enabled =
preference_manager_.GetBoolean(PrefNames::kAdvancedProtectionEnabled,
/*default_value=*/false);
bool mendel_advanced_protection_enabled =
!NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
kSenderSkipsConfirmation);
bool advanced_protection_mismatch =
(be_advanced_protection_enabled != mendel_advanced_protection_enabled);
// Continue to use mendel flag until we have confidence that the Nearby BE
// flag has the same value.
session->SetAdvancedProtectionStatus(mendel_advanced_protection_enabled,
advanced_protection_mismatch);
if (session->token().empty() || !mendel_advanced_protection_enabled) {
session->SetAdvancedProtectionStatus(protection_enabled,
/*advanced_protection_mismatch=*/false);
if (session->token().empty() || !protection_enabled) {
// Auto accept if no token or if advanced protection is disabled.
OutgoingSessionAccept(*session);
} else {
@@ -2931,12 +2756,6 @@ void NearbySharingServiceImpl::OnIncomingFilesMetadataUpdated(
// ShareTarget already disconnected.
return;
}
fast_initiation_scanner_cooldown_timer_ = std::make_unique<ThreadTimer>(
*service_thread_, "fast_initiation_scanner_cooldown_timer",
kFastInitiationScannerCooldown, [this]() {
fast_initiation_scanner_cooldown_timer_.reset();
InvalidateFastInitiationScanning();
});
// Make sure to call this before calling Disconnect, or we risk losing
// some transfer updates in the receive case due to the Disconnect call
// cleaning up share targets.
@@ -3054,20 +2873,6 @@ IncomingShareSession* NearbySharingServiceImpl::GetIncomingShareSession(
return &it->second;
}
std::optional<std::vector<uint8_t>>
NearbySharingServiceImpl::GetBluetoothMacAddressForShareTarget(
OutgoingShareSession& session) {
const std::optional<NearbyShareDecryptedPublicCertificate>& certificate =
session.certificate();
if (!certificate) {
LOG(ERROR) << __func__ << ": No decrypted public certificate found for "
<< "share target id: " << session.share_target().id;
return std::nullopt;
}
return GetBluetoothMacAddressFromCertificate(*certificate);
}
void NearbySharingServiceImpl::UnregisterShareTarget(int64_t share_target_id) {
LOG(INFO) << __func__ << ": Unregister share target " << share_target_id;
@@ -3093,21 +2898,20 @@ 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);
}
}
@@ -3179,15 +2983,11 @@ void NearbySharingServiceImpl::SetInHighVisibility(
service_observers_.NotifyHighVisibilityChanged(in_high_visibility_);
}
void NearbySharingServiceImpl::OnNetworkChanged(
nearby::ConnectivityManager::ConnectionType type) {
void NearbySharingServiceImpl::OnLanConnectedChanged(bool connected) {
on_network_changed_delay_timer_ = std::make_unique<ThreadTimer>(
*service_thread_, "on_network_changed_delay_timer",
kProcessNetworkChangeTimerDelay,
[this]() { StopAdvertisingAndInvalidateSurfaceState(); });
}
void NearbySharingServiceImpl::OnLanConnectedChanged(bool connected) {
RunOnNearbySharingServiceThread(
"lan_connection_changed", [this, connected]() {
VLOG(1) << __func__
+9 -21
View File
@@ -52,7 +52,6 @@
#include "sharing/internal/api/preference_manager.h"
#include "sharing/internal/api/sharing_platform.h"
#include "sharing/internal/api/sharing_rpc_client.h"
#include "sharing/internal/public/connectivity_manager.h"
#include "sharing/internal/public/context.h"
#include "sharing/local_device_data/nearby_share_local_device_data_manager.h"
#include "sharing/nearby_connection.h"
@@ -103,7 +102,10 @@ class NearbySharingServiceImpl
NearbySharingServiceImpl(
std::unique_ptr<nearby::TaskRunner> service_thread, Context* context,
nearby::sharing::api::SharingPlatform& sharing_platform,
std::unique_ptr<nearby::sharing::api::SharingRpcClientFactory>
nearby_share_client_factory,
std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager,
std::unique_ptr<NearbyShareContactManager> contact_manager,
analytics::AnalyticsRecorder* analytics_recorder);
~NearbySharingServiceImpl() override;
@@ -275,11 +277,6 @@ class NearbySharingServiceImpl
StatusCodes StopScanning();
void StopAdvertisingAndInvalidateSurfaceState();
void InvalidateFastInitiationScanning();
void StartFastInitiationScanning();
void OnFastInitiationDevicesNotDetected();
void StopFastInitiationScanning();
void ScheduleRotateBackgroundAdvertisementTimer();
void OnRotateBackgroundAdvertisementTimerFired();
@@ -290,11 +287,8 @@ class NearbySharingServiceImpl
absl::string_view endpoint_id,
NearbyConnection* connection, Status status);
void CreatePayloads(
OutgoingShareSession& session,
std::function<void(OutgoingShareSession&, bool)> callback);
void OnCreatePayloads(std::vector<uint8_t> endpoint_info,
OutgoingShareSession& session, bool success);
void OutgoingSessionConnect(OutgoingShareSession& session,
std::vector<uint8_t> endpoint_info);
void Fail(IncomingShareSession& session, TransferMetadata::Status status);
void OnIncomingAdvertisementDecoded(
@@ -350,9 +344,6 @@ class NearbySharingServiceImpl
ShareSession* GetShareSession(int64_t share_target_id);
IncomingShareSession* GetIncomingShareSession(int64_t share_target_id);
std::optional<std::vector<uint8_t>> GetBluetoothMacAddressForShareTarget(
OutgoingShareSession& session);
void UnregisterShareTarget(int64_t share_target_id);
void OnStartAdvertisingResult(bool used_device_name, Status status);
@@ -369,7 +360,6 @@ class NearbySharingServiceImpl
bool is_initiator_of_cancellation);
// Monitor connectivity changes.
void OnNetworkChanged(nearby::ConnectivityManager::ConnectionType type);
void OnLanConnectedChanged(bool connected);
// Resets all settings of the nearby sharing service.
@@ -455,10 +445,12 @@ class NearbySharingServiceImpl
// Registers the most recent TransferMetadata and ShareTarget used for
// transitioning notifications between foreground surfaces and background
// surfaces. Empty if no metadata is available.
std::optional<std::tuple<ShareTarget, AttachmentContainer, TransferMetadata>>
std::optional<std::tuple<ShareTarget, std::unique_ptr<AttachmentContainer>,
TransferMetadata>>
last_incoming_metadata_;
// The most recent outgoing TransferMetadata and ShareTarget.
std::optional<std::tuple<ShareTarget, AttachmentContainer, TransferMetadata>>
std::optional<std::tuple<ShareTarget, std::unique_ptr<AttachmentContainer>,
TransferMetadata>>
last_outgoing_metadata_;
// A map of ShareTarget id to IncomingShareSession. This lets us know which
// Nearby Connections endpoint and public certificate are related to the
@@ -498,10 +490,6 @@ class NearbySharingServiceImpl
// Used to debounce OnNetworkChanged processing.
std::unique_ptr<ThreadTimer> on_network_changed_delay_timer_;
// Used to prevent the "Device nearby is sharing" notification from appearing
// immediately after a completed share.
std::unique_ptr<ThreadTimer> fast_initiation_scanner_cooldown_timer_;
// A queue of endpoint-discovered and endpoint-lost events that ensures the
// events are processed sequentially, in the order received from Nearby
// Connections. An event is processed either immediately, if there are no
File diff suppressed because it is too large Load Diff
+4 -26
View File
@@ -23,6 +23,7 @@
#include <vector>
#include "absl/hash/hash.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "internal/base/file_path.h"
@@ -33,34 +34,9 @@
#include "sharing/common/nearby_share_enums.h"
#include "sharing/internal/base/encode.h"
#include "sharing/internal/public/logging.h"
#include "sharing/nearby_sharing_service.h"
namespace nearby::sharing {
std::string ReceiveSurfaceStateToString(
NearbySharingService::ReceiveSurfaceState state) {
switch (state) {
case NearbySharingService::ReceiveSurfaceState::kForeground:
return "FOREGROUND";
case NearbySharingService::ReceiveSurfaceState::kBackground:
return "BACKGROUND";
case NearbySharingService::ReceiveSurfaceState::kUnknown:
return "UNKNOWN";
}
}
std::string SendSurfaceStateToString(
NearbySharingService::SendSurfaceState state) {
switch (state) {
case NearbySharingService::SendSurfaceState::kForeground:
return "FOREGROUND";
case NearbySharingService::SendSurfaceState::kBackground:
return "BACKGROUND";
case NearbySharingService::SendSurfaceState::kUnknown:
return "UNKNOWN";
}
}
std::string PowerLevelToString(PowerLevel level) {
switch (level) {
case PowerLevel::kLowPower:
@@ -131,7 +107,9 @@ std::string GetDeviceId(
}
if (!certificate->id().empty()) {
return std::string(certificate->id().begin(), certificate->id().end());
return absl::BytesToHexString(absl::string_view(
reinterpret_cast<const char*>(certificate->id().data()),
certificate->id().size()));
}
return std::string(endpoint_id);
-7
View File
@@ -27,7 +27,6 @@
#include "sharing/advertisement.h"
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
#include "sharing/common/nearby_share_enums.h"
#include "sharing/nearby_sharing_service.h"
namespace nearby::sharing {
@@ -48,12 +47,6 @@ std::optional<std::string> GetDeviceName(
const Advertisement& advertisement,
const std::optional<NearbyShareDecryptedPublicCertificate>& certificate);
std::string ReceiveSurfaceStateToString(
NearbySharingService::ReceiveSurfaceState state);
std::string SendSurfaceStateToString(
NearbySharingService::SendSurfaceState state);
std::string PowerLevelToString(PowerLevel level);
// Return the most stable device identifier with the following priority:
+71
View File
@@ -0,0 +1,71 @@
// 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/nearby_sharing_util.h"
#include <optional>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
#include "sharing/certificates/nearby_share_encrypted_metadata_key.h"
#include "sharing/certificates/nearby_share_private_certificate.h"
#include "sharing/proto/encrypted_metadata.pb.h"
#include "sharing/proto/enums.pb.h"
#include "sharing/proto/rpc_resources.pb.h"
namespace nearby::sharing {
TEST(GetDeviceIdTest, CertificateAvailable_NoMacAddress_HasCertificateId) {
const std::string kEndpointId = "endpoint-123";
// Create metadata without Bluetooth MAC address
nearby::sharing::proto::EncryptedMetadata metadata;
metadata.set_device_name("TestDevice");
// Create private certificate
NearbySharePrivateCertificate private_cert(
nearby::sharing::proto::DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE,
absl::Now(), metadata);
// Generate EncryptedMetadataKey
std::optional<NearbyShareEncryptedMetadataKey> encrypted_metadata_key =
private_cert.EncryptMetadataKey();
ASSERT_TRUE(encrypted_metadata_key.has_value());
// Generate PublicCertificate
std::optional<nearby::sharing::proto::PublicCertificate> public_cert =
private_cert.ToPublicCertificate();
ASSERT_TRUE(public_cert.has_value());
// Decrypt PublicCertificate
std::optional<NearbyShareDecryptedPublicCertificate> certificate =
NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
*public_cert, *encrypted_metadata_key);
ASSERT_TRUE(certificate.has_value());
// Calculate expected Device ID from certificate ID
std::string expected_device_id = absl::BytesToHexString(
absl::string_view(reinterpret_cast<const char*>(certificate->id().data()),
certificate->id().size()));
EXPECT_EQ(GetDeviceId(kEndpointId, certificate), expected_device_id);
}
} // namespace nearby::sharing
+74 -38
View File
@@ -14,7 +14,6 @@
#include "sharing/outgoing_share_session.h"
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
@@ -28,6 +27,7 @@
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/platform/clock.h"
#include "internal/platform/task_runner.h"
#include "sharing/analytics/analytics_recorder.h"
@@ -39,7 +39,7 @@
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/nearby_sharing_util.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/payload_tracker.h"
#include "sharing/share_session.h"
@@ -110,6 +110,19 @@ ConnectionLayerStatus ConvertToConnectionLayerStatus(Status status) {
}
}
std::optional<std::vector<uint8_t>> GetBluetoothMacAddressForShareTarget(
OutgoingShareSession& session) {
const std::optional<NearbyShareDecryptedPublicCertificate>& certificate =
session.certificate();
if (!certificate) {
LOG(ERROR) << __func__ << ": No decrypted public certificate found for "
<< "share target id: " << session.share_target().id;
return std::nullopt;
}
return GetBluetoothMacAddressFromCertificate(*certificate);
}
} // namespace
OutgoingShareSession::OutgoingShareSession(
@@ -129,12 +142,16 @@ OutgoingShareSession::~OutgoingShareSession() = default;
void OutgoingShareSession::InvokeTransferUpdateCallback(
const TransferMetadata& metadata) {
if (metadata.is_final_status()) {
is_connecting_ = false;
}
transfer_update_callback_(*this, metadata);
}
void OutgoingShareSession::InitiateSendAttachments(
bool OutgoingShareSession::InitiateSendAttachments(
std::unique_ptr<AttachmentContainer> attachment_container) {
SetAttachmentContainer(std::move(*attachment_container));
is_connecting_ = true;
// Set session ID.
set_session_id(analytics_recorder().GenerateNextId());
@@ -144,6 +161,31 @@ void OutgoingShareSession::InitiateSendAttachments(
/*transfer_position=*/1,
/*concurrent_connections=*/1,
share_target());
text_payloads_.clear();
wifi_credentials_payloads_.clear();
file_payloads_.clear();
CreateTextPayloads();
CreateWifiCredentialsPayloads();
bool success = CreateFilePayloads();
// Log analytics event of describing attachments.
analytics_recorder().NewDescribeAttachments(this->attachment_container());
if (success) {
if (text_payloads_.empty() && wifi_credentials_payloads_.empty() &&
file_payloads_.empty()) {
// Fails in no payloads created.
success = false;
}
}
if (!success) {
LOG(WARNING) << __func__
<< ": Failed to send file to remote ShareTarget. Failed to "
"create payloads.";
UpdateTransferMetadata(
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kMediaUnavailable)
.build());
}
return success;
}
bool OutgoingShareSession::ProcessKeyVerificationResult(
@@ -160,25 +202,12 @@ void OutgoingShareSession::OnConnectionDisconnected() {
}
}
std::vector<FilePath> OutgoingShareSession::GetFilePaths() const {
std::vector<FilePath> file_paths;
file_paths.reserve(attachment_container().GetFileAttachments().size());
for (const FileAttachment& file_attachment :
attachment_container().GetFileAttachments()) {
// All file attachments must have a file path.
// That is verified in SendAttachments().
file_paths.push_back(*file_attachment.file_path());
}
return file_paths;
}
void OutgoingShareSession::CreateTextPayloads() {
const std::vector<TextAttachment> attachments =
const std::vector<TextAttachment>& attachments =
attachment_container().GetTextAttachments();
if (attachments.empty()) {
return;
}
text_payloads_.clear();
text_payloads_.reserve(attachments.size());
for (const TextAttachment& attachment : attachments) {
absl::string_view body = attachment.text_body();
@@ -189,12 +218,11 @@ void OutgoingShareSession::CreateTextPayloads() {
}
void OutgoingShareSession::CreateWifiCredentialsPayloads() {
const std::vector<WifiCredentialsAttachment> attachments =
const std::vector<WifiCredentialsAttachment>& attachments =
attachment_container().GetWifiCredentialsAttachments();
if (attachments.empty()) {
return;
}
wifi_credentials_payloads_.clear();
wifi_credentials_payloads_.reserve(attachments.size());
for (const WifiCredentialsAttachment& attachment : attachments) {
nearby::sharing::service::proto::WifiCredentials wifi_credentials;
@@ -210,26 +238,26 @@ void OutgoingShareSession::CreateWifiCredentialsPayloads() {
}
}
bool OutgoingShareSession::CreateFilePayloads(
const std::vector<NearbyFileHandler::FileInfo>& files) {
AttachmentContainer& container = mutable_attachment_container();
if (files.size() != container.GetFileAttachments().size()) {
return false;
}
if (files.empty()) {
bool OutgoingShareSession::CreateFilePayloads() {
if (attachment_container().GetFileAttachments().empty()) {
return true;
}
file_payloads_.clear();
file_payloads_.reserve(files.size());
AttachmentContainer& container = mutable_attachment_container();
file_payloads_.reserve(container.GetFileAttachments().size());
for (size_t i = 0; i < files.size(); ++i) {
const NearbyFileHandler::FileInfo& file_info = files[i];
for (int i = 0; i < container.GetFileAttachments().size(); ++i) {
FileAttachment& attachment = container.GetMutableFileAttachment(i);
attachment.set_size(file_info.size);
InputFile input_file;
input_file.path = file_info.file_path;
Payload payload(input_file, attachment.parent_folder());
payload.content.file_payload.size = file_info.size;
// All file attachments must have a file path.
// That is verified in SendAttachments().
FilePath file_path = *attachment.file_path();
std::optional<uintmax_t> file_size = Files::GetFileSize(file_path);
if (!file_size.has_value()) {
LOG(WARNING) << "Failed to get file size for file: "
<< file_path.ToString();
return false;
}
attachment.set_size(*file_size);
Payload payload(file_path, attachment.parent_folder());
file_payloads_.push_back(std::move(payload));
SetAttachmentPayloadId(attachment.id(), file_payloads_.back().id);
}
@@ -499,6 +527,8 @@ bool OutgoingShareSession::UpdateSessionForDedup(
<< "Share target id cannot be changed during deduplication.";
set_share_target(share_target);
if (IsConnected()) {
LOG(INFO) << __func__ << ": session for share_target.id=" << share_target.id
<< " is connected, not updating.";
return false;
}
set_endpoint_id(endpoint_id);
@@ -512,15 +542,20 @@ bool OutgoingShareSession::UpdateSessionForDedup(
void OutgoingShareSession::Connect(
std::vector<uint8_t> endpoint_info,
std::optional<std::vector<uint8_t>> bluetooth_mac_address,
DataUsage data_usage, bool disable_wifi_hotspot,
std::function<void(absl::string_view endpoint_id,
NearbyConnection* connection, Status status)>
callback) {
// Send process initialized successfully, from now on status updated
// will be sent out via TransferUpdates.
UpdateTransferMetadata(TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kConnecting)
.build());
connection_start_time_ = clock().Now();
connections_manager().Connect(
std::move(endpoint_info), endpoint_id(), std::move(bluetooth_mac_address),
data_usage, GetTransportType(disable_wifi_hotspot), std::move(callback));
std::move(endpoint_info), endpoint_id(),
GetBluetoothMacAddressForShareTarget(*this), data_usage,
GetTransportType(disable_wifi_hotspot), std::move(callback));
}
bool OutgoingShareSession::OnConnectResult(NearbyConnection* connection,
@@ -547,6 +582,7 @@ bool OutgoingShareSession::OnConnectResult(NearbyConnection* connection,
}
set_disconnect_status(TransferMetadata::Status::kFailed);
SetConnection(connection);
is_connecting_ = false;
// Log analytics event of establishing connection.
analytics_recorder().NewEstablishConnection(
+23 -23
View File
@@ -26,7 +26,6 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "internal/platform/clock.h"
#include "internal/platform/task_runner.h"
#include "sharing/analytics/analytics_recorder.h"
@@ -35,7 +34,6 @@
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/proto/enums.pb.h"
#include "sharing/share_session.h"
@@ -69,32 +67,15 @@ class OutgoingShareSession : public ShareSession {
obfuscated_gaia_id_ = std::move(obfuscated_gaia_id);
}
const std::vector<Payload>& text_payloads() const { return text_payloads_; }
const std::vector<Payload>& wifi_credentials_payloads() const {
return wifi_credentials_payloads_;
}
const std::vector<Payload>& file_payloads() const { return file_payloads_; }
void InitiateSendAttachments(
// Returns true if the attachments are valid and payloads are created
// successfully.
bool InitiateSendAttachments(
std::unique_ptr<AttachmentContainer> attachment_container);
bool ProcessKeyVerificationResult(
PairedKeyVerificationRunner::PairedKeyVerificationResult result,
location::nearby::proto::sharing::OSType share_target_os_type);
std::vector<FilePath> GetFilePaths() const;
void CreateTextPayloads();
void CreateWifiCredentialsPayloads();
// Create file payloads and update the file size of all file attachments.
// The list of file infos must be sorted in the same order as the file
// attachments in the share target.
// Returns true if all file payloads are created successfully.
bool CreateFilePayloads(
const std::vector<NearbyFileHandler::FileInfo>& files);
// Returns true if the introduction frame is written successfully.
// `timeout_callback` is called if accept is not received from both sender and
// receiver within the timeout.
@@ -150,7 +131,6 @@ class OutgoingShareSession : public ShareSession {
// Establish a connection to the remote device identified by `endpoint_info`.
// `callback` is called when with the connection establishment status..
void Connect(std::vector<uint8_t> endpoint_info,
std::optional<std::vector<uint8_t>> bluetooth_mac_address,
nearby::sharing::proto::DataUsage data_usage,
bool disable_wifi_hotspot,
std::function<void(absl::string_view endpoint_id,
@@ -169,6 +149,19 @@ class OutgoingShareSession : public ShareSession {
advanced_protection_mismatch_ = advanced_protection_mismatch;
}
// Returns true if the session is connected or in the process of connecting.
bool IsActive() const {
return IsConnected() || is_connecting_;
}
const std::vector<Payload>& text_payloads() const { return text_payloads_; }
const std::vector<Payload>& wifi_credentials_payloads() const {
return wifi_credentials_payloads_;
}
const std::vector<Payload>& file_payloads() const { return file_payloads_; }
protected:
void InvokeTransferUpdateCallback(const TransferMetadata& metadata) override;
void OnConnectionDisconnected() override;
@@ -181,6 +174,12 @@ class OutgoingShareSession : public ShareSession {
bool FillIntroductionFrame(
nearby::sharing::service::proto::IntroductionFrame* introduction) const;
void CreateTextPayloads();
void CreateWifiCredentialsPayloads();
// Create file payloads and update the file size of all file attachments.
// Returns true if all file payloads are created successfully.
bool CreateFilePayloads();
std::optional<std::string> obfuscated_gaia_id_;
// All payloads are in the same order as the attachments in the share target.
std::vector<Payload> text_payloads_;
@@ -199,6 +198,7 @@ class OutgoingShareSession : public ShareSession {
std::unique_ptr<ThreadTimer> disconnection_timeout_;
bool advanced_protection_enabled_ = false;
bool advanced_protection_mismatch_ = false;
bool is_connecting_ = false;
};
} // namespace nearby::sharing
+160 -206
View File
@@ -15,6 +15,7 @@
#include "sharing/outgoing_share_session.h"
#include <cstdint>
#include <fstream>
#include <memory>
#include <optional>
#include <string>
@@ -29,6 +30,7 @@
#include "internal/analytics/mock_event_logger.h"
#include "internal/analytics/sharing_log_matchers.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/network/url.h"
#include "internal/test/fake_clock.h"
#include "internal/test/fake_device_info.h"
@@ -43,7 +45,6 @@
#include "sharing/nearby_connection_impl.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/proto/analytics/nearby_sharing_log.pb.h"
#include "sharing/proto/analytics/nearby_sharing_log.proto.static_reflection.h"
@@ -72,6 +73,7 @@ using ::nearby::sharing::service::proto::WifiCredentials;
using ::testing::_;
using ::testing::AllOf;
using ::testing::Eq;
using ::testing::InSequence;
using ::testing::IsEmpty;
using ::testing::IsFalse;
using ::testing::IsTrue;
@@ -83,6 +85,16 @@ using ::testing::StrictMock;
using ::testing::proto::ProtoField;
constexpr absl::string_view kEndpointId = "ABCD";
constexpr absl::string_view kFile1Name = "someFileName.jpg";
constexpr int kFile1Size = 1234;
void CreateTempFile(absl::string_view file_name, int file_size) {
FilePath file_path =
Files::GetTemporaryDirectory().append(FilePath(file_name));
std::ofstream file_stream(file_path.GetPath());
file_stream << std::string(file_size, 'a');
file_stream.close();
}
class OutgoingShareSessionTest : public ::testing::Test {
public:
@@ -94,29 +106,36 @@ class OutgoingShareSessionTest : public ::testing::Test {
"A bit of text body", "Some text title", "text/html"),
text2_(nearby::sharing::service::proto::TextMetadata::ADDRESS,
"A bit of text body 2", "Some text title 2", "text/plain"),
file1_(FilePath("/usr/local/tmp/someFileName.jpg"), /*mime_type=*/"",
file1_(Files::GetTemporaryDirectory().append(FilePath(kFile1Name)),
/*mime_type=*/"",
/*parent_folder=*/"/usr/local/parent"),
file2_(FilePath("/usr/local/tmp/someFileName2.jpg"), /*mime_type=*/"",
/*parent_folder=*/"/usr/local/parent2"),
wifi1_(
"GoogleGuest",
nearby::sharing::service::proto::WifiCredentialsMetadata::WPA_PSK,
"somepassword", /*is_hidden=*/true) {}
std::unique_ptr<AttachmentContainer> CreateDefaultAttachmentContainer() {
return std::make_unique<AttachmentContainer>(
std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
"somepassword", /*is_hidden=*/true) {
CreateTempFile(kFile1Name, kFile1Size);
}
void InitSendAttachments(
std::unique_ptr<AttachmentContainer> CreateDefaultAttachmentContainer() {
return AttachmentContainer::Builder(
std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_})
.Build();
}
bool InitSendAttachments(
std::unique_ptr<AttachmentContainer> attachment_container) {
InSequence seq;
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(
AllOf((HasCategory(EventCategory::SENDING_EVENT),
HasEventType(EventType::SEND_START))))));
session_.InitiateSendAttachments(std::move(attachment_container));
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(
AllOf((HasCategory(EventCategory::SENDING_EVENT),
HasEventType(EventType::DESCRIBE_ATTACHMENTS))))));
return session_.InitiateSendAttachments(std::move(attachment_container));
}
void ConnectionSuccess(NearbyConnection* connection) {
@@ -125,7 +144,10 @@ class OutgoingShareSessionTest : public ::testing::Test {
AllOf((HasCategory(EventCategory::SENDING_EVENT),
HasEventType(EventType::ESTABLISH_CONNECTION))))));
connections_manager_.set_nearby_connection(connection);
session_.Connect({}, {}, proto::DataUsage::ONLINE_DATA_USAGE,
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(/*endpoint_info=*/{}, proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/false,
[](absl::string_view endpoint_id,
NearbyConnection* connection, Status status) {});
@@ -148,156 +170,108 @@ class OutgoingShareSessionTest : public ::testing::Test {
TextAttachment text1_;
TextAttachment text2_;
FileAttachment file1_;
FileAttachment file2_;
WifiCredentialsAttachment wifi1_;
};
TEST_F(OutgoingShareSessionTest, GetFilePaths) {
OutgoingShareSession session(
&fake_clock_, fake_task_runner_, &connections_manager_,
analytics_recorder_, std::string(kEndpointId), share_target_,
[](OutgoingShareSession&, const TransferMetadata&) {});
auto container = std::make_unique<AttachmentContainer>(
std::vector<TextAttachment>{},
std::vector<FileAttachment>{file1_, file2_},
std::vector<WifiCredentialsAttachment>{});
session.InitiateSendAttachments(std::move(container));
TEST_F(OutgoingShareSessionTest, InitiateSendAttachmentsWithNoAttachments) {
EXPECT_CALL(
transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kMediaUnavailable),
IsFinalStatus())));
auto file_paths = session.GetFilePaths();
EXPECT_THAT(
InitSendAttachments(AttachmentContainer::Builder({}, {}, {}).Build()),
IsFalse());
ASSERT_THAT(file_paths, SizeIs(2));
EXPECT_THAT(file_paths[0], Eq(file1_.file_path()));
EXPECT_THAT(file_paths[1], Eq(file2_.file_path()));
EXPECT_THAT(session_.text_payloads(), IsEmpty());
EXPECT_THAT(session_.wifi_credentials_payloads(), IsEmpty());
EXPECT_THAT(session_.file_payloads(), IsEmpty());
}
TEST_F(OutgoingShareSessionTest, CreateTextPayloadsWithNoTextAttachments) {
OutgoingShareSession session(
&fake_clock_, fake_task_runner_, &connections_manager_,
analytics_recorder_, std::string(kEndpointId), share_target_,
[](OutgoingShareSession&, const TransferMetadata&) {});
session.CreateTextPayloads();
const std::vector<Payload>& payloads = session.text_payloads();
TEST_F(OutgoingShareSessionTest, InitiateSendAttachmentsSuccess) {
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
EXPECT_THAT(payloads, IsEmpty());
}
TEST_F(OutgoingShareSessionTest, CreateTextPayloads) {
InitSendAttachments(CreateDefaultAttachmentContainer());
session_.CreateTextPayloads();
const std::vector<Payload>& payloads = session_.text_payloads();
auto& attachment_payload_map = session_.attachment_payload_map();
ASSERT_THAT(payloads, SizeIs(2));
EXPECT_THAT(payloads[0].content.type, Eq(PayloadContent::Type::kBytes));
EXPECT_THAT(payloads[1].content.type, Eq(PayloadContent::Type::kBytes));
EXPECT_THAT(payloads[0].content.bytes_payload.bytes,
const std::vector<Payload>& text_payloads = session_.text_payloads();
ASSERT_THAT(text_payloads, SizeIs(2));
EXPECT_THAT(text_payloads[0].content.type, Eq(PayloadContent::Type::kBytes));
EXPECT_THAT(text_payloads[1].content.type, Eq(PayloadContent::Type::kBytes));
EXPECT_THAT(text_payloads[0].content.bytes_payload.bytes,
Eq(std::vector<uint8_t>(text1_.text_body().begin(),
text1_.text_body().end())));
EXPECT_THAT(payloads[1].content.bytes_payload.bytes,
EXPECT_THAT(text_payloads[1].content.bytes_payload.bytes,
Eq(std::vector<uint8_t>(text2_.text_body().begin(),
text2_.text_body().end())));
ASSERT_THAT(attachment_payload_map, SizeIs(2));
ASSERT_THAT(attachment_payload_map.contains(text1_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(text1_.id()), Eq(payloads[0].id));
ASSERT_THAT(attachment_payload_map.contains(text2_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(text2_.id()), Eq(payloads[1].id));
}
const std::vector<Payload>& wifi_payloads =
session_.wifi_credentials_payloads();
TEST_F(OutgoingShareSessionTest, CreateFilePayloadsWithNoFileAttachments) {
OutgoingShareSession session(
&fake_clock_, fake_task_runner_, &connections_manager_,
analytics_recorder_, std::string(kEndpointId), share_target_,
[](OutgoingShareSession&, const TransferMetadata&) {});
EXPECT_THAT(
session.CreateFilePayloads(std::vector<NearbyFileHandler::FileInfo>()),
IsTrue());
const std::vector<Payload>& payloads = session.file_payloads();
EXPECT_THAT(payloads, IsEmpty());
}
TEST_F(OutgoingShareSessionTest, CreateFilePayloadsWithWrongFileInfo) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(
session_.CreateFilePayloads(std::vector<NearbyFileHandler::FileInfo>()),
IsFalse());
const std::vector<Payload>& payloads = session_.file_payloads();
EXPECT_THAT(payloads, IsEmpty());
}
TEST_F(OutgoingShareSessionTest, CreateFilePayloads) {
InitSendAttachments(CreateDefaultAttachmentContainer());
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
session_.CreateFilePayloads(file_infos);
const std::vector<Payload>& payloads = session_.file_payloads();
auto& attachment_payload_map = session_.attachment_payload_map();
ASSERT_THAT(payloads, SizeIs(1));
EXPECT_THAT(payloads[0].content.type, Eq(PayloadContent::Type::kFile));
EXPECT_THAT(payloads[0].content.file_payload.size, Eq(12355L));
EXPECT_THAT(payloads[0].content.file_payload.parent_folder,
Eq(file1_.parent_folder()));
EXPECT_THAT(payloads[0].content.file_payload.file.path,
Eq(file1_.file_path()));
EXPECT_THAT(attachment_payload_map, SizeIs(1));
ASSERT_THAT(attachment_payload_map.contains(file1_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(file1_.id()), Eq(payloads[0].id));
EXPECT_THAT(session_.attachment_container().GetFileAttachments()[0].size(),
Eq(12355L));
}
TEST_F(OutgoingShareSessionTest, CreateWifiPayloadsWithNoWifiAttachments) {
OutgoingShareSession session(
&fake_clock_, fake_task_runner_, &connections_manager_,
analytics_recorder_, std::string(kEndpointId), share_target_,
[](OutgoingShareSession&, const TransferMetadata&) {});
session.CreateWifiCredentialsPayloads();
const std::vector<Payload>& payloads = session.file_payloads();
EXPECT_THAT(payloads, IsEmpty());
}
TEST_F(OutgoingShareSessionTest, CreateWifiCredentialsPayloads) {
InitSendAttachments(CreateDefaultAttachmentContainer());
session_.CreateWifiCredentialsPayloads();
const std::vector<Payload>& payloads = session_.wifi_credentials_payloads();
auto& attachment_payload_map = session_.attachment_payload_map();
ASSERT_THAT(payloads, SizeIs(1));
EXPECT_THAT(payloads[0].content.type, Eq(PayloadContent::Type::kBytes));
ASSERT_THAT(wifi_payloads, SizeIs(1));
EXPECT_THAT(wifi_payloads[0].content.type, Eq(PayloadContent::Type::kBytes));
WifiCredentials wifi_credentials;
EXPECT_THAT(wifi_credentials.ParseFromArray(
payloads[0].content.bytes_payload.bytes.data(),
payloads[0].content.bytes_payload.bytes.size()),
wifi_payloads[0].content.bytes_payload.bytes.data(),
wifi_payloads[0].content.bytes_payload.bytes.size()),
IsTrue());
EXPECT_THAT(wifi_credentials.password(), Eq(wifi1_.password()));
EXPECT_THAT(wifi_credentials.has_hidden_ssid(), Eq(wifi1_.is_hidden()));
ASSERT_THAT(attachment_payload_map, SizeIs(1));
const std::vector<Payload>& file_payloads = session_.file_payloads();
ASSERT_THAT(file_payloads, SizeIs(1));
EXPECT_THAT(file_payloads[0].content.type, Eq(PayloadContent::Type::kFile));
EXPECT_THAT(file_payloads[0].content.file_payload.parent_folder,
Eq(file1_.parent_folder()));
EXPECT_THAT(file_payloads[0].content.file_payload.file_path,
Eq(file1_.file_path()));
EXPECT_THAT(session_.attachment_container().GetFileAttachments()[0].size(),
Eq(kFile1Size));
auto& attachment_payload_map = session_.attachment_payload_map();
ASSERT_THAT(attachment_payload_map, SizeIs(4));
ASSERT_THAT(attachment_payload_map.contains(text1_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(text1_.id()), Eq(text_payloads[0].id));
ASSERT_THAT(attachment_payload_map.contains(text2_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(text2_.id()), Eq(text_payloads[1].id));
ASSERT_THAT(attachment_payload_map.contains(wifi1_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(wifi1_.id()), Eq(payloads[0].id));
EXPECT_THAT(attachment_payload_map.at(wifi1_.id()), Eq(wifi_payloads[0].id));
ASSERT_THAT(attachment_payload_map.contains(file1_.id()), IsTrue());
EXPECT_THAT(attachment_payload_map.at(file1_.id()), Eq(file_payloads[0].id));
}
TEST_F(OutgoingShareSessionTest,
InitiateSendAttachmentsWithNonexistentFileAttachment) {
// Remove attachment file1.
Files::RemoveFile(
Files::GetTemporaryDirectory().append(FilePath(kFile1Name)));
EXPECT_CALL(
transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kMediaUnavailable),
IsFinalStatus())));
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsFalse());
const std::vector<Payload>& payloads = session_.file_payloads();
EXPECT_THAT(payloads, IsEmpty());
}
TEST_F(OutgoingShareSessionTest, ConnectNoDisableWifiHotspot) {
std::vector<uint8_t> endpoint_info = {1, 2, 3, 4};
std::vector<uint8_t> bluetooth_mac_address = {5, 6, 7, 8};
file1_.set_size(1000000); // 1MB
InitSendAttachments(CreateDefaultAttachmentContainer());
// Set file size to 1MB.
CreateTempFile(kFile1Name, 1000000);
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
NearbyConnectionImpl nearby_connection(device_info_);
connections_manager_.set_nearby_connection(&nearby_connection);
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(
endpoint_info, bluetooth_mac_address,
nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
endpoint_info, nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/false,
[&nearby_connection](absl::string_view endpoint_id,
NearbyConnection* connection, Status status) {
@@ -317,15 +291,18 @@ TEST_F(OutgoingShareSessionTest, ConnectNoDisableWifiHotspot) {
TEST_F(OutgoingShareSessionTest, ConnectDisableWifiHotspot) {
std::vector<uint8_t> endpoint_info = {1, 2, 3, 4};
std::vector<uint8_t> bluetooth_mac_address = {5, 6, 7, 8};
file1_.set_size(1000000); // 1MB
InitSendAttachments(CreateDefaultAttachmentContainer());
// Set file size to 1MB.
CreateTempFile(kFile1Name, 1000000);
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
NearbyConnectionImpl nearby_connection(device_info_);
connections_manager_.set_nearby_connection(&nearby_connection);
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(
endpoint_info, bluetooth_mac_address,
nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
endpoint_info, nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/true,
[&nearby_connection](absl::string_view endpoint_id,
NearbyConnection* connection, Status status) {
@@ -344,15 +321,17 @@ TEST_F(OutgoingShareSessionTest, ConnectDisableWifiHotspot) {
}
TEST_F(OutgoingShareSessionTest, OnConnectResultSuccessLogsSessionDuration) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
std::vector<uint8_t> endpoint_info = {1, 2, 3, 4};
std::vector<uint8_t> bluetooth_mac_address = {5, 6, 7, 8};
NearbyConnectionImpl nearby_connection(device_info_);
connections_manager_.set_nearby_connection(&nearby_connection);
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(
endpoint_info, bluetooth_mac_address,
nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
endpoint_info, nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/false,
[&nearby_connection](absl::string_view endpoint_id,
NearbyConnection* connection, Status status) {
@@ -375,11 +354,14 @@ TEST_F(OutgoingShareSessionTest, OnConnectResultSuccessLogsSessionDuration) {
}
TEST_F(OutgoingShareSessionTest, OnConnectResultFailureLogsSessionDuration) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
std::vector<uint8_t> endpoint_info = {1, 2, 3, 4};
std::vector<uint8_t> bluetooth_mac_address = {5, 6, 7, 8};
session_.Connect(endpoint_info, bluetooth_mac_address,
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(endpoint_info,
nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/false,
[](absl::string_view endpoint_id,
@@ -403,24 +385,12 @@ TEST_F(OutgoingShareSessionTest, OnConnectResultFailureLogsSessionDuration) {
IsFalse());
}
TEST_F(OutgoingShareSessionTest, SendIntroductionWithoutPayloads) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(session_.SendIntroduction([]() {}), IsFalse());
}
TEST_F(OutgoingShareSessionTest, SendIntroductionSuccess) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
session_.CreateFilePayloads(file_infos);
session_.CreateTextPayloads();
session_.CreateWifiCredentialsPayloads();
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(AllOf(
(HasCategory(EventCategory::SENDING_EVENT),
@@ -465,7 +435,7 @@ TEST_F(OutgoingShareSessionTest, SendIntroductionSuccess) {
ASSERT_THAT(intro_frame.file_metadata_size(), Eq(1));
EXPECT_THAT(intro_frame.file_metadata(0).id(), Eq(file1_.id()));
// File attachment size has been updated by CreateFilePayloads().
EXPECT_THAT(intro_frame.file_metadata(0).size(), Eq(file_infos[0].size));
EXPECT_THAT(intro_frame.file_metadata(0).size(), Eq(kFile1Size));
EXPECT_THAT(intro_frame.file_metadata(0).name(), Eq(file1_.file_name()));
EXPECT_THAT(intro_frame.file_metadata(0).payload_id(),
Eq(file_payloads[0].id));
@@ -485,14 +455,15 @@ TEST_F(OutgoingShareSessionTest, SendIntroductionSuccess) {
}
TEST_F(OutgoingShareSessionTest, SendIntroductionTimeout) {
auto container = std::make_unique<AttachmentContainer>(
std::vector<TextAttachment>{text1_}, std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{});
InitSendAttachments(std::move(container));
auto container =
AttachmentContainer::Builder(std::vector<TextAttachment>{text1_},
std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{})
.Build();
EXPECT_THAT(InitSendAttachments(std::move(container)), IsTrue());
session_.set_session_id(1234);
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
session_.CreateTextPayloads();
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(AllOf(
(HasCategory(EventCategory::SENDING_EVENT),
@@ -511,14 +482,15 @@ TEST_F(OutgoingShareSessionTest, SendIntroductionTimeout) {
}
TEST_F(OutgoingShareSessionTest, SendIntroductionTimeoutCancelled) {
auto container = std::make_unique<AttachmentContainer>(
std::vector<TextAttachment>{text1_}, std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{});
InitSendAttachments(std::move(container));
auto container =
AttachmentContainer::Builder(std::vector<TextAttachment>{text1_},
std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{})
.Build();
EXPECT_THAT(InitSendAttachments(std::move(container)), IsTrue());
session_.set_session_id(1234);
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
session_.CreateTextPayloads();
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(AllOf(
(HasCategory(EventCategory::SENDING_EVENT),
@@ -561,14 +533,15 @@ TEST_F(OutgoingShareSessionTest, AcceptTransferNotReady) {
}
TEST_F(OutgoingShareSessionTest, AcceptTransferSuccess) {
auto container = std::make_unique<AttachmentContainer>(
std::vector<TextAttachment>{text1_}, std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{});
InitSendAttachments(std::move(container));
auto container =
AttachmentContainer::Builder(std::vector<TextAttachment>{text1_},
std::vector<FileAttachment>{},
std::vector<WifiCredentialsAttachment>{})
.Build();
EXPECT_THAT(InitSendAttachments(std::move(container)), IsTrue());
session_.set_session_id(1234);
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
session_.CreateTextPayloads();
EXPECT_CALL(mock_event_logger_,
Log(Matcher<const SharingLog&>(AllOf(
(HasCategory(EventCategory::SENDING_EVENT),
@@ -669,16 +642,9 @@ TEST_F(OutgoingShareSessionTest, HandleConnectionResponseAcceptResponse) {
}
TEST_F(OutgoingShareSessionTest, SendPayloads) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
session_.CreateFilePayloads(file_infos);
session_.CreateTextPayloads();
session_.CreateWifiCredentialsPayloads();
MockFunction<void()> payload_transder_update_callback;
StrictMock<MockFunction<void(
std::unique_ptr<Payload>,
@@ -715,16 +681,9 @@ TEST_F(OutgoingShareSessionTest, SendPayloads) {
}
TEST_F(OutgoingShareSessionTest, SendPayloadsSetsAdvancedProtectionFlags) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
session_.CreateFilePayloads(file_infos);
session_.CreateTextPayloads();
session_.CreateWifiCredentialsPayloads();
MockFunction<void()> payload_transder_update_callback;
StrictMock<MockFunction<void(
std::unique_ptr<Payload>,
@@ -763,16 +722,9 @@ TEST_F(OutgoingShareSessionTest, SendPayloadsSetsAdvancedProtectionFlags) {
}
TEST_F(OutgoingShareSessionTest, SendNextPayload) {
InitSendAttachments(CreateDefaultAttachmentContainer());
EXPECT_THAT(InitSendAttachments(CreateDefaultAttachmentContainer()),
IsTrue());
session_.set_session_id(1234);
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
session_.CreateFilePayloads(file_infos);
session_.CreateTextPayloads();
session_.CreateWifiCredentialsPayloads();
MockFunction<void()> payload_transder_update_callback;
StrictMock<MockFunction<void(
std::unique_ptr<Payload>,
@@ -895,8 +847,10 @@ TEST_F(OutgoingShareSessionTest, DelayCompleteDisconnectTimeout) {
NearbyConnectionImpl connection(device_info_);
session_.set_session_id(1234);
std::vector<uint8_t> endpoint_info = {1, 2, 3, 4};
std::vector<uint8_t> bluetooth_mac_address = {5, 6, 7, 8};
session_.Connect(endpoint_info, bluetooth_mac_address,
EXPECT_CALL(transfer_metadata_callback_,
Call(_, AllOf(HasStatus(TransferMetadata::Status::kConnecting),
Not(IsFinalStatus()))));
session_.Connect(endpoint_info,
nearby::sharing::proto::DataUsage::ONLINE_DATA_USAGE,
/*disable_wifi_hotspot=*/false,
[&](absl::string_view endpoint_id,
+206 -162
View File
@@ -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,24 @@
#include <stdint.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#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,157 +47,188 @@
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::DeduplicateInOutgoingShareTarget(
const ShareTarget& share_target, absl::string_view endpoint_id,
void OutgoingTargetsManager::OnShareTargetDiscovered(
ShareTarget share_target, absl::string_view endpoint_id,
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
// TODO(b/343764269): may need to update last_outgoing_metadata_ if the
// deduped target id matches the one in last_outgoing_metadata_.
// But since we do not modify the share target of a connected session, it may
// not happen.
auto session_it = outgoing_share_session_map_.find(share_target.id);
if (session_it == outgoing_share_session_map_.end()) {
LOG(WARNING) << __func__ << ": share_target.id=" << share_target.id
<< " not found in outgoing share session map.";
std::optional<int64_t> old_id =
FindExistingTargetId(endpoint_id, share_target);
if (old_id.has_value()) {
// If the duplicate is found, share_target.id needs to be updated to the old
// "discovered" share_target_id so ShareTarget updates matches a target
// that was discovered before.
share_target.id = *old_id;
LOG(INFO) << __func__
<< ": ShareTarget updated, endpoint_id: " << endpoint_id
<< ", share_target: " << share_target.ToString();
auto session_it = outgoing_share_session_map_.find(*old_id);
if (session_it != outgoing_share_session_map_.end()) {
OutgoingShareSession& session = session_it->second;
std::string old_endpoint_id = session.endpoint_id();
if (session.UpdateSessionForDedup(share_target, std::move(certificate),
endpoint_id) &&
old_endpoint_id != endpoint_id) {
// Session updated and endpoint_id changed. Need to update endpoint id
// to share target id mapping.
outgoing_target_id_map_.erase(old_endpoint_id);
outgoing_target_id_map_.insert(
{std::string(endpoint_id), share_target.id});
}
}
share_target_updated_callback_(share_target);
return;
}
if (session_it->second.IsConnected()) {
LOG(INFO) << __func__ << ": share_target.id=" << share_target.id
<< " is connected, not updating outgoing_share_session_map_.";
return;
old_id = FindInDiscoveryCache(endpoint_id, share_target);
bool in_discovery_cache = old_id.has_value();
if (in_discovery_cache) {
share_target.id = *old_id;
}
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();
<< (in_discovery_cache ? ": Recovered from discovery cache"
: ": Discovered new target")
<< ": endpoint_id=" << endpoint_id
<< ", share_target=" << share_target.ToString();
AddTarget(share_target, endpoint_id, std::move(certificate));
if (in_discovery_cache) {
share_target_updated_callback_(share_target);
} else {
share_target_discovered_callback_(share_target);
}
}
bool OutgoingTargetsManager::FindDuplicateInDiscoveryCache(
absl::string_view endpoint_id, ShareTarget& share_target) {
std::optional<int64_t> OutgoingTargetsManager::FindInDiscoveryCache(
absl::string_view endpoint_id, const ShareTarget& share_target) {
auto it = discovery_cache_.find(endpoint_id);
if (it != discovery_cache_.end()) {
int64_t old_id = it->second.share_target.id;
// If endpoint info changes for an endpoint ID, NC will send a rediscovery
// event for the same endpoint id.
LOG(INFO) << __func__
<< ": [Dedupped] Found duplicate endpoint_id: " << endpoint_id
<< ", share_target.id changed from: " << share_target.id << " to "
<< it->second.share_target.id;
share_target.id = it->second.share_target.id;
LOG(INFO) << __func__ << ": Found existing endpoint_id: " << endpoint_id
<< ", mapping share_target.id: " << share_target.id
<< " to: " << it->second.share_target.id;
discovery_cache_.erase(it);
return true;
return old_id;
}
for (auto it = discovery_cache_.begin(); it != discovery_cache_.end(); ++it) {
if (it->second.share_target.device_id == share_target.device_id) {
LOG(INFO) << __func__
<< ": [Dedupped] Found duplicate device_id, share_target.id "
"changed from: "
<< share_target.id << " to " << it->second.share_target.id
<< ". New endpoint_id: " << endpoint_id;
// Share targets in discovery cache have receive_disabled set to true.
// Copy only the id field from cache entry,
share_target.id = it->second.share_target.id;
discovery_cache_.erase(it);
return true;
}
}
return false;
}
bool OutgoingTargetsManager::FindDuplicateInOutgoingShareTargets(
absl::string_view endpoint_id, ShareTarget& share_target) {
// If the duplicate is found, share_target.id needs to be updated to the old
// "discovered" share_target_id so NotifyShareTargetUpdated matches a target
// that was discovered before.
auto it = outgoing_share_target_map_.find(endpoint_id);
if (it != outgoing_share_target_map_.end()) {
// If endpoint info changes for an endpoint ID, NC will send a rediscovery
// event for the same endpoint id.
LOG(INFO) << __func__
<< ": [Dedupped] Found duplicate endpoint_id: " << endpoint_id
<< " in outgoing_share_target_map, share_target.id changed from: "
<< share_target.id << " to " << it->second.id;
share_target.id = it->second.id;
it->second = share_target;
return true;
}
for (auto it = outgoing_share_target_map_.begin();
it != outgoing_share_target_map_.end(); ++it) {
if (it->second.device_id == share_target.device_id) {
LOG(INFO)
<< __func__
<< ": [Dedupped] Found duplicate device_id, endpoint ID "
"changed from: "
<< it->first << " to " << endpoint_id
<< " in outgoing_share_target_map, share_target.id changed from: "
<< share_target.id << " to " << it->second.id;
share_target.id = it->second.id;
outgoing_share_target_map_.erase(it);
outgoing_share_target_map_.insert_or_assign(endpoint_id, share_target);
return true;
}
}
return false;
}
std::optional<ShareTarget>
OutgoingTargetsManager::RemoveOutgoingShareTargetWithEndpointId(
absl::string_view endpoint_id) {
VLOG(1) << __func__ << ":Outgoing connection to " << endpoint_id
<< " disconnected";
auto target_node = outgoing_share_target_map_.extract(endpoint_id);
if (target_node.empty()) {
LOG(WARNING) << __func__ << ": endpoint_id=" << endpoint_id
<< " not found in outgoing share target map.";
if (share_target.device_id.empty()) {
// Do not match empty device_id.
return std::nullopt;
}
ShareTarget& share_target = target_node.mapped();
VLOG(1) << __func__ << ": Removing (endpoint_id=" << endpoint_id
<< ", share_target.id=" << target_node.mapped().id
<< ") from outgoing share target map";
auto device_id_it = std::find_if(
discovery_cache_.begin(), discovery_cache_.end(),
[&share_target](const auto& pair) {
return pair.second.share_target.device_id == share_target.device_id;
});
if (device_id_it != discovery_cache_.end()) {
int64_t old_id = device_id_it->second.share_target.id;
LOG(INFO) << __func__
<< ": Found existing device_id, updating endpoint ID: "
<< device_id_it->first << " to: " << endpoint_id
<< " , mapping share_target.id: " << share_target.id
<< " to: " << old_id;
discovery_cache_.erase(device_id_it);
return old_id;
}
return std::nullopt;
}
std::optional<int64_t> OutgoingTargetsManager::FindExistingTargetId(
absl::string_view endpoint_id,
const ShareTarget& share_target) {
auto it = outgoing_target_id_map_.find(endpoint_id);
if (it != outgoing_target_id_map_.end()) {
int64_t old_share_target_id = it->second;
// If endpoint info changes for an endpoint ID, NC will send a rediscovery
// event for the same endpoint id.
LOG(INFO) << __func__ << ": Found existing endpoint_id: " << endpoint_id
<< ", mapping share_target.id: " << share_target.id
<< " to: " << old_share_target_id;
return old_share_target_id;
}
if (share_target.device_id.empty()) {
// Do not match empty device_id.
return std::nullopt;
}
auto device_id_it = std::find_if(
outgoing_share_session_map_.begin(), outgoing_share_session_map_.end(),
[&share_target](const auto& pair) {
return pair.second.share_target().device_id == share_target.device_id;
});
if (device_id_it != outgoing_share_session_map_.end()) {
int64_t old_share_target_id = device_id_it->second.share_target().id;
LOG(INFO) << __func__
<< ": Found existing device_id, updating endpoint ID: "
<< device_id_it->first << " to: " << endpoint_id
<< " , mapping share_target.id: " << share_target.id
<< " to: " << old_share_target_id;
return old_share_target_id;
}
return std::nullopt;
}
std::optional<ShareTarget> OutgoingTargetsManager::RemoveTarget(
absl::string_view endpoint_id, bool close_connected) {
VLOG(1) << __func__ << ":Removing endpoint_id " << endpoint_id;
auto it = outgoing_target_id_map_.find(endpoint_id);
if (it == outgoing_target_id_map_.end()) {
LOG(WARNING) << __func__ << ": endpoint_id=" << endpoint_id
<< " not found.";
return std::nullopt;
}
int64_t share_target_id = it->second;
auto session_it = outgoing_share_session_map_.find(share_target_id);
if (session_it == outgoing_share_session_map_.end()) {
LOG(ERROR) << __func__ << ": share_target.id=" << share_target_id
<< " not found in outgoing share session map.";
outgoing_target_id_map_.erase(it);
return std::nullopt;
}
if (!close_connected && session_it->second.IsActive()) {
LOG(INFO) << __func__ << ": share_target.id=" << share_target_id
<< " is active, not removing.";
return std::nullopt;
}
VLOG(1) << __func__
<< ": Removing share_target.id=" << share_target_id
<< " from outgoing share target map";
outgoing_target_id_map_.erase(it);
// Do not destroy the session until it has been removed from the map.
// Session destruction can trigger callbacks that traverses the map and it
// cannot access the map while it is being modified.
auto session_node =
outgoing_share_session_map_.extract(target_node.mapped().id);
if (!session_node.empty()) {
session_node.mapped().OnDisconnect();
} else {
LOG(WARNING) << __func__ << ": share_target.id=" << target_node.mapped().id
<< " not found in outgoing share session map.";
}
return share_target;
auto session_node = outgoing_share_session_map_.extract(session_it);
ShareTarget removed_target = session_node.mapped().share_target();
session_node.mapped().OnDisconnect();
return std::move(removed_target);
}
// 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.
// outgoing_target_id_map_ in this function, and some callers like
// 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);
RemoveTarget(endpoint_id, /*close_connected=*/false);
if (!share_target_opt.has_value()) {
return;
}
@@ -205,8 +238,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
@@ -214,46 +246,54 @@ void OutgoingTargetsManager::MoveToDiscoveryCache(std::string endpoint_id,
return;
}
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";
LOG(INFO) << ": ShareTarget lost after retention: " << retention
<< ", endpoint_id=" << endpoint_id
<< ", share_target=" << share_target.ToString();
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.
LOG(INFO) << __func__
<< ": ShareTarget disabled, endpoint_id: " << endpoint_id << ", "
<< cache_entry.share_target.ToString();
share_target_updated_callback_(cache_entry.share_target);
auto [it, inserted] =
discovery_cache_.insert_or_assign(endpoint_id, std::move(cache_entry));
LOG(INFO) << "[Dedupped] added to discovery_cache: " << endpoint_id << " by "
<< (inserted ? "insert" : "assign");
discovery_cache_.insert_or_assign(endpoint_id, std::move(cache_entry));
}
void OutgoingTargetsManager::CreateOutgoingShareSession(
void OutgoingTargetsManager::AddTarget(
const ShareTarget& share_target, absl::string_view endpoint_id,
std::optional<NearbyShareDecryptedPublicCertificate> certificate,
absl::AnyInvocable<void(OutgoingShareSession& session,
const TransferMetadata& metadata)>
transfer_update_callback) {
outgoing_share_target_map_.insert_or_assign(endpoint_id, share_target);
auto [it_out, inserted] = outgoing_share_session_map_.try_emplace(
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
auto [target_it, target_inserted] = outgoing_target_id_map_.insert(
{std::string(endpoint_id), share_target.id});
if (!target_inserted) {
if (target_it->second != share_target.id) {
LOG(ERROR) << __func__ << ": endpoint_id=" << endpoint_id
<< " already associated with share_target id="
<< target_it->second
<< ", cannot replace with share_target id=" << share_target.id;
return;
}
LOG(WARNING) << __func__ << ": endpoint_id=" << endpoint_id
<< " already exists, share target not updated.";
}
auto [session_it, session_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));
if (!inserted) {
transfer_update_callback_);
if (!session_inserted) {
LOG(WARNING) << __func__ << ": share_target.id=" << share_target.id
<< " already exists in outgoing share session map. This "
"should NOT happen";
} else {
auto& session = it_out->second;
if (certificate.has_value()) {
session.set_certificate(std::move(*certificate));
if (session_it->second.IsConnected()) {
LOG(WARNING) << __func__
<< ": session for share_target.id=" << share_target.id
<< " is connected, certificate not updated.";
return;
}
}
auto& session = session_it->second;
if (certificate.has_value()) {
session.set_certificate(std::move(*certificate));
}
}
OutgoingShareSession* OutgoingTargetsManager::GetOutgoingShareSession(
@@ -266,22 +306,26 @@ 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));
std::vector<std::string> endpoint_ids_to_remove;
endpoint_ids_to_remove.reserve(outgoing_target_id_map_.size());
for (const auto& [endpoint_id, share_target_id] : outgoing_target_id_map_) {
endpoint_ids_to_remove.push_back(endpoint_id);
}
for (const auto& endpoint_id : endpoint_ids_to_remove) {
OnShareTargetLost(endpoint_id, retention);
}
DCHECK(outgoing_share_target_map_.empty());
DCHECK(outgoing_share_session_map_.empty());
}
void OutgoingTargetsManager::Cleanup() {
while (!outgoing_share_target_map_.empty()) {
RemoveOutgoingShareTargetWithEndpointId(
outgoing_share_target_map_.begin()->first);
std::vector<std::string> endpoint_ids_to_remove;
endpoint_ids_to_remove.reserve(outgoing_target_id_map_.size());
for (const auto& [endpoint_id, share_target_id] : outgoing_target_id_map_) {
endpoint_ids_to_remove.push_back(endpoint_id);
}
for (const auto& endpoint_id : endpoint_ids_to_remove) {
RemoveTarget(endpoint_id, /*close_connected=*/true);
}
discovery_cache_.clear();
}
@@ -293,8 +337,8 @@ void OutgoingTargetsManager::ForEachShareTarget(
for (const auto& [endpoint_id, discovery_cache_entry] : discovery_cache_) {
callback(discovery_cache_entry.share_target);
}
for (const auto& [endpoint_id, share_target] : outgoing_share_target_map_) {
callback(share_target);
for (const auto& [target_id, session] : outgoing_share_session_map_) {
callback(session.share_target());
}
}
+67 -47
View File
@@ -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,67 +42,81 @@
#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);
// 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);
// Move all outgoing share targets to the discovery cache so that they will be
// reported as receive_disabled.
void DisableAllOutgoingShareTargets();
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);
// Call OnShareTargetLost() on all known share targets.
void AllTargetsLost(absl::Duration retention);
void ForEachShareTarget(
absl::AnyInvocable<void(const ShareTarget&)> callback);
private:
// If an existing target matching either endpoint_id or share_target.device_id
// is found, the existing share target id is returned.
// Otherwise, std::nullopt is returned.
std::optional<int64_t> FindExistingTargetId(
absl::string_view endpoint_id,
const ShareTarget& share_target);
// Looks for existing share target in the discovery cache.
// If found, the share target is removed from the discovery cache and its
// id is returned.
// Otherwise, std::nullopt is returned.
std::optional<int64_t> FindInDiscoveryCache(absl::string_view endpoint_id,
const ShareTarget& share_target);
void AddTarget(
const ShareTarget& share_target, absl::string_view endpoint_id,
std::optional<NearbyShareDecryptedPublicCertificate> certificate);
// Returns the share target if it has been removed, std::nullopt otherwise.
std::optional<ShareTarget> RemoveOutgoingShareTargetWithEndpointId(
absl::string_view endpoint_id);
// If `close_connected` is false, connected session will not be closed.
std::optional<ShareTarget> RemoveTarget(absl::string_view endpoint_id,
bool close_connected);
// Cache a recently lost share target to be re-discovered.
// Purged after expiry_timer.
@@ -113,13 +130,16 @@ 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_;
// A map of endpoint id to ShareTarget, where each ShareTarget entry
// directly corresponds to a OutgoingShareSession entry in
// outgoing_share_target_info_map_;
absl::flat_hash_map<std::string, ShareTarget> outgoing_share_target_map_;
std::function<void(OutgoingShareSession& session,
const TransferMetadata& metadata)>
transfer_update_callback_;
// A map of endpoint id to ShareTarget id, where each ShareTarget id refers to
// an OutgoingShareSession entry in outgoing_share_target_info_map_;
absl::flat_hash_map<std::string, int64_t> outgoing_target_id_map_;
// A map of ShareTarget id to OutgoingShareSession. This lets us know which
// endpoint and public certificate are related to the outgoing share target.
absl::flat_hash_map<int64_t, OutgoingShareSession>
+785
View File
@@ -0,0 +1,785 @@
// 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 <vector>
#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_device_info.h"
#include "internal/test/fake_task_runner.h"
#include "sharing/analytics/analytics_recorder.h"
#include "sharing/attachment_container.h"
#include "sharing/fake_nearby_connections_manager.h"
#include "sharing/nearby_connection_impl.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/outgoing_share_session.h"
#include "sharing/share_target.h"
#include "sharing/text_attachment.h"
#include "sharing/transfer_metadata.h"
namespace nearby::sharing {
namespace {
using ::absl::Seconds;
using ::testing::ElementsAre;
using ::testing::InSequence;
using ::testing::SizeIs;
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_;
FakeDeviceInfo device_info_;
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, onShareTargetLostConnectedNotClosed) {
constexpr int kShareTargetId = 1234;
constexpr absl::string_view kEndpointId = "endpoint_id";
ShareTarget target;
target.id = kShareTargetId;
{
InSequence s;
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);
ASSERT_NE(session, nullptr);
NearbyConnectionImpl connection(device_info_);
session->OnConnectResult(&connection, Status::kSuccess);
ASSERT_TRUE(session->IsConnected());
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, target);
});
EXPECT_TRUE(has_targets);
session = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
EXPECT_TRUE(session->IsConnected());
// 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_EQ(share_target, target);
});
EXPECT_TRUE(has_targets);
session = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
EXPECT_TRUE(session->IsConnected());
}
TEST_F(OutgoingTargetsManagerTest, onShareTargetLostConnectingNotClosed) {
constexpr int kShareTargetId = 1234;
constexpr absl::string_view kEndpointId = "endpoint_id";
ShareTarget target;
target.id = kShareTargetId;
{
InSequence s;
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);
ASSERT_NE(session, nullptr);
// InitiateSendAttachments is called when session starts connecting.
session->InitiateSendAttachments(
AttachmentContainer::Builder()
.AddTextAttachment(TextAttachment(
nearby::sharing::service::proto::TextMetadata::ADDRESS,
"A bit of text body 2", "Some text title 2", "text/plain"))
.Build());
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, target);
});
EXPECT_TRUE(has_targets);
session = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, 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_EQ(share_target, target);
});
EXPECT_TRUE(has_targets);
session = outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
}
TEST_F(OutgoingTargetsManagerTest, onShareTargeDedupByEndpointIdNoLoss) {
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,
onShareTargeDedupByEndpointIdNoLossConnected) {
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);
OutgoingShareSession* session =
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
NearbyConnectionImpl connection(device_info_);
session->OnConnectResult(&connection, Status::kSuccess);
ASSERT_TRUE(session->IsConnected());
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);
// Make sure endpoint id is not updated since session is already connected.
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, onShareTargeDedupByDeviceIdNoLossConnected) {
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);
OutgoingShareSession* session =
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
NearbyConnectionImpl connection(device_info_);
session->OnConnectResult(&connection, Status::kSuccess);
ASSERT_TRUE(session->IsConnected());
// 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);
// Make sure endpoint id is not updated since session is already connected.
EXPECT_EQ(session2->endpoint_id(), kEndpointId1);
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, onShareTargeDedupByDeviceIdNoLoss) {
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(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);
// 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);
}
TEST_F(OutgoingTargetsManagerTest, onShareTargeNoDedupOnEmptyDeviceId) {
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";
target2.device_id = "";
{
InSequence s;
EXPECT_CALL(share_target_discovered_callback_, Call)
.WillOnce([&](const ShareTarget& share_target) {
EXPECT_EQ(share_target, target);
});
EXPECT_CALL(share_target_updated_callback_, Call)
.WillOnce([&](const ShareTarget& share_target) {
EXPECT_EQ(share_target, disabled_target);
});
EXPECT_CALL(share_target_discovered_callback_, Call)
.WillOnce([&](const ShareTarget& share_target) {
EXPECT_EQ(share_target, target2);
});
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(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(kShareTargetId),
nullptr);
// Make sure share session is created for original target id.
OutgoingShareSession* session2 =
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId2);
EXPECT_NE(session2, nullptr);
EXPECT_EQ(session2->share_target(), target2);
EXPECT_EQ(session2->endpoint_id(), kEndpointId2);
std::vector<ShareTarget> share_targets;
outgoing_targets_manager_.ForEachShareTarget(
[&](const ShareTarget& share_target) {
share_targets.push_back(share_target);
});
EXPECT_THAT(share_targets, SizeIs(2));
EXPECT_THAT(share_targets, ElementsAre(disabled_target, target2));
}
TEST_F(OutgoingTargetsManagerTest, CleanupClosesConnectedSessions) {
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).Times(0);
EXPECT_CALL(share_target_lost_callback_, Call).Times(0);
EXPECT_CALL(transfer_update_callback_, Call)
.WillOnce([&](OutgoingShareSession& session,
const TransferMetadata& metadata) {
EXPECT_EQ(session.endpoint_id(), kEndpointId);
EXPECT_EQ(session.share_target(), target);
EXPECT_EQ(metadata.status(), TransferMetadata::Status::kFailed);
});
}
outgoing_targets_manager_.OnShareTargetDiscovered(
target, kEndpointId, /*certificate=*/std::nullopt);
OutgoingShareSession* session =
outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId);
ASSERT_NE(session, nullptr);
NearbyConnectionImpl connection(device_info_);
session->OnConnectResult(&connection, Status::kSuccess);
ASSERT_TRUE(session->IsConnected());
outgoing_targets_manager_.Cleanup();
bool has_targets = false;
outgoing_targets_manager_.ForEachShareTarget(
[&](const ShareTarget& share_target) {
has_targets = true;
});
EXPECT_FALSE(has_targets);
EXPECT_EQ(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
nullptr);
}
TEST_F(OutgoingTargetsManagerTest, AllTargetsLostClosesConnectedSessions) {
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(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_.AllTargetsLost(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);
}
TEST_F(OutgoingTargetsManagerTest, AllTargetsLostConnectedSessionsNotClosed) {
constexpr int kShareTargetId = 1234;
constexpr absl::string_view kEndpointId = "endpoint_id";
ShareTarget target;
target.id = kShareTargetId;
{
InSequence s;
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);
ASSERT_NE(session, nullptr);
NearbyConnectionImpl connection(device_info_);
session->OnConnectResult(&connection, Status::kSuccess);
ASSERT_TRUE(session->IsConnected());
outgoing_targets_manager_.AllTargetsLost(Seconds(10));
bool has_targets = false;
outgoing_targets_manager_.ForEachShareTarget(
[&](const ShareTarget& share_target) {
has_targets = true;
EXPECT_EQ(share_target, target);
});
EXPECT_TRUE(has_targets);
EXPECT_NE(outgoing_targets_manager_.GetOutgoingShareSession(kShareTargetId),
nullptr);
}
} // namespace
} // namespace nearby::sharing
+11 -10
View File
@@ -33,8 +33,7 @@
#include "sharing/proto/wire_format.pb.h"
#include "sharing/transfer_metadata.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
namespace {
constexpr int64_t kShareTargetId = 123456789L;
@@ -46,16 +45,19 @@ constexpr absl::string_view kMimeType = "image/jpg";
class PayloadTrackerTest : public ::testing::Test {
public:
void SetUp() override {
container_.AddFileAttachment(FileAttachment(
kFileId, kFileSize, std::string(kFileName), std::string(kMimeType),
service::proto::FileMetadata::IMAGE));
container_ =
AttachmentContainer::Builder()
.AddFileAttachment(FileAttachment(
kFileId, kFileSize, std::string(kFileName),
std::string(kMimeType), service::proto::FileMetadata::IMAGE))
.Build();
attachment_payload_map_.clear();
attachment_payload_map_.emplace(container_.GetFileAttachments()[0].id(),
attachment_payload_map_.emplace(container_->GetFileAttachments()[0].id(),
kFileId);
auto payload_updates_queue =
std::make_unique<PayloadTracker::PayloadUpdateQueue>(&task_runner_);
payload_tracker_ = std::make_unique<PayloadTracker>(
&fake_clock_, kShareTargetId, container_, attachment_payload_map_,
&fake_clock_, kShareTargetId, *container_, attachment_payload_map_,
std::move(payload_updates_queue));
}
@@ -74,7 +76,7 @@ class PayloadTrackerTest : public ::testing::Test {
FakeClock fake_clock_;
FakeTaskRunner task_runner_{&fake_clock_, 1};
std::unique_ptr<PayloadTracker> payload_tracker_ = nullptr;
AttachmentContainer container_;
std::unique_ptr<AttachmentContainer> container_;
absl::flat_hash_map<int64_t, int64_t> attachment_payload_map_;
};
@@ -102,5 +104,4 @@ TEST_F(PayloadTrackerTest, StatusUpdateWithTimeUpdate) {
}
} // namespace
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
@@ -30,7 +30,7 @@ option objc_class_prefix = "GNCP";
// Top-level log proto for all NearbySharing logging.
// Each log contains a key (event_type), value (a verb-noun event) pair.
// Next Tag: 87
// Next Tag: 90
// LINT.IfChange
message SharingLog {
/* justification = {
@@ -235,6 +235,13 @@ message SharingLog {
optional CloudUploadEnd cloud_upload_end = 86;
optional CloudDownloadStart cloud_download_start = 87;
optional CloudDownloadEnd cloud_download_end = 88;
// Cloud sharing RPC call event.
optional CloudSharingRpcResult cloud_sharing_rpc_result = 89;
// Used only for Nearby Share Windows app now.
message AppInfo {
// e.g. "1.0.408"
@@ -483,6 +490,9 @@ message SharingLog {
// provider is not external.
optional string external_provider_id = 11
/* type = ST_SESSION_ID */;
// Is this file transfer from a direct share target. This is only available
// for the sender log.
optional bool is_direct_share = 12;
}
// TODO(fdi): may consider adding a field about decipherability later.
@@ -615,6 +625,9 @@ message SharingLog {
optional int32 connection_medium = 14;
// The data usage of the user settings.
optional location.nearby.proto.sharing.DataUsage data_usage = 15;
// True if the sender and receiver are mutual contacts.
optional bool is_mutual_contact = 16;
}
// EventType: RECEIVE_ATTACHMENTS_START
@@ -914,6 +927,7 @@ message SharingLog {
ANDROID_APP = 3;
AUDIO = 4;
DOCUMENT = 5;
CONTACT_CARD = 6;
}
}
@@ -1046,20 +1060,66 @@ message SharingLog {
// EventType: CLOUD_CREATE_SHARING_REQUEST
message CloudCreateSharingRequest {
optional AttachmentsInfo attachments_info = 1;
optional location.nearby.proto.sharing.CloudCreateSharingResult result = 2;
// Time taken to download attachments from the Intent in milliseconds.
optional int64 attachment_download_latency_millis = 3;
// Time taken to generate and encrypt the preview thumbnail in milliseconds.
optional int64 preview_thumbnail_latency_millis = 4;
// Time taken to make the CreateSharing RPC call in milliseconds.
optional int64 rpc_latency_millis = 5;
}
// EventType: CLOUD_REGISTER_RECEIVER used by QR code cloud web receiver
message CloudRegisterReceiver {}
message CloudRegisterReceiver {
optional location.nearby.proto.sharing.CloudRegisterReceiverResult result =
1;
}
// EventType: CLOUD_UPLOAD_START used by QR code cloud web sender
// The cloud_sharing_id and flow_id are logged in the event metadata.
message CloudUploadStart {
optional AttachmentsInfo attachments_info = 1;
optional location.nearby.proto.sharing.CloudActionType action_type = 2;
}
// EventType: CLOUD_UPLOAD_END used by QR code cloud web sender
// The cloud_sharing_id and flow_id are logged in the event metadata.
message CloudUploadEnd {
repeated CloudAttachmentInfo upload_infos = 1;
optional location.nearby.proto.sharing.CloudActionType action_type = 2;
}
// EventType: CLOUD_DOWNLOAD_START used by QR code cloud web receiver
// The cloud_sharing_id and cloud_receiver_session_id are logged in the
// event_metadata into the anonymous logs.
message CloudDownloadStart {
optional AttachmentsInfo attachments_info = 1;
optional location.nearby.proto.sharing.CloudActionType action_type = 2;
}
// EventType: CLOUD_DOWNLOAD_END used by QR code cloud web receiver
// The cloud_sharing_id and cloud_receiver_session_id are logged in the
// event_metadata into the anonymous logs.
message CloudDownloadEnd {
repeated CloudAttachmentInfo download_infos = 1;
optional location.nearby.proto.sharing.CloudActionType action_type = 2;
}
// EventType: CLOUD_SHARING_RPC_RESULT
// Event logging the result of a Cloud Sharing RPC call. This event captures
// the type of RPC, its outcome, and performance metrics.
message CloudSharingRpcResult {
// The specific RPC method that was called.
optional string rpc_name = 1;
// The canonical gRPC status code (io.grpc.Status.Code) resulting from the
// call.
optional int32 status_code = 2;
// The total time taken for the RPC call to complete, in milliseconds.
optional int64 latency_millis = 3;
// The unique identifier for the cloud sharing session, if available at the
// time of the call. This helps correlate RPC events to a specific sharing
// session.
optional string cloud_sharing_id = 4;
}
}
// LINT.ThenChange(//depot/google3/logs/proto/location/nearby/nearby_client_log.proto)
@@ -78,10 +78,8 @@ NearbyShareSchedulerBase::NearbyShareSchedulerBase(
}
if (require_connectivity_) {
connectivity_manager_->RegisterConnectionListener(
connection_listener_name_,
[this](nearby::ConnectivityManager::ConnectionType connection_type,
bool is_lan_connected, bool is_internet_connected) {
connectivity_manager_->RegisterInternetListener(
connection_listener_name_, [this](bool is_internet_connected) {
OnInternetConnectivityChanged(is_internet_connected);
});
}
@@ -89,7 +87,7 @@ NearbyShareSchedulerBase::NearbyShareSchedulerBase(
NearbyShareSchedulerBase::~NearbyShareSchedulerBase() {
if (require_connectivity_) {
connectivity_manager_->UnregisterConnectionListener(
connectivity_manager_->UnregisterInternetListener(
connection_listener_name_);
}
}
@@ -154,8 +152,7 @@ absl::Duration NearbyShareSchedulerBase::GetTimeUntilNextRequest() const {
// Recover from failures using exponential backoff strategy if necessary.
absl::Duration time_until_retry = TimeUntilRetry(now);
if (time_until_retry != absl::InfiniteDuration())
return time_until_retry;
if (time_until_retry != absl::InfiniteDuration()) return time_until_retry;
// Schedule the periodic request if applicable.
return TimeUntilRecurringRequest(now);
@@ -184,9 +181,7 @@ size_t NearbyShareSchedulerBase::GetNumConsecutiveFailures() const {
return pref_value.value();
}
void NearbyShareSchedulerBase::OnStart() {
Reschedule();
}
void NearbyShareSchedulerBase::OnStart() { Reschedule(); }
void NearbyShareSchedulerBase::OnStop() { timer_->Stop(); }
+18 -12
View File
@@ -72,31 +72,37 @@ std::string TokenToFourDigitString(const std::vector<uint8_t>& bytes) {
} // namespace
/* static */
// Only used for final statuses.
AttachmentTransmissionStatus ShareSession::ConvertToTransmissionStatus(
TransferMetadata::Status status) {
switch (status) {
case TransferMetadata::Status::kComplete:
return AttachmentTransmissionStatus::
COMPLETE_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kCancelled:
return AttachmentTransmissionStatus::
CANCELED_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kFailed:
return AttachmentTransmissionStatus::
FAILED_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kIncompletePayloads:
return AttachmentTransmissionStatus::FAILED_NO_PAYLOAD;
case TransferMetadata::Status::kRejected:
return AttachmentTransmissionStatus::
REJECTED_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kCancelled:
return AttachmentTransmissionStatus::
CANCELED_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kTimedOut:
return AttachmentTransmissionStatus::
TIMED_OUT_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kMediaUnavailable:
return AttachmentTransmissionStatus::MEDIA_UNAVAILABLE_ATTACHMENT;
case TransferMetadata::Status::kDeviceAuthenticationFailed:
return AttachmentTransmissionStatus::FAILED_PAIRED_KEYHANDSHAKE;
case TransferMetadata::Status::kRejected:
return AttachmentTransmissionStatus::REJECTED_ATTACHMENT;
case TransferMetadata::Status::kTimedOut:
return AttachmentTransmissionStatus::TIMED_OUT_ATTACHMENT;
case TransferMetadata::Status::kNotEnoughSpace:
return AttachmentTransmissionStatus::
NOT_ENOUGH_SPACE_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kUnsupportedAttachmentType:
return AttachmentTransmissionStatus::
UNSUPPORTED_ATTACHMENT_TYPE_ATTACHMENT;
UNSUPPORTED_ATTACHMENT_TYPE_ATTACHMENT_TRANSMISSION_STATUS;
case TransferMetadata::Status::kDeviceAuthenticationFailed:
return AttachmentTransmissionStatus::FAILED_PAIRED_KEYHANDSHAKE;
case TransferMetadata::Status::kIncompletePayloads:
return AttachmentTransmissionStatus::FAILED_NO_PAYLOAD;
default:
return AttachmentTransmissionStatus::
UNKNOWN_ATTACHMENT_TRANSMISSION_STATUS;
+4 -5
View File
@@ -24,6 +24,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "internal/network/url.h"
#include "sharing/common/nearby_share_enums.h"
@@ -41,14 +42,14 @@ ShareTarget::ShareTarget() { id = ++kLastGeneratedId; }
ShareTarget::ShareTarget(
std::string device_name, Url image_url, ShareTargetType type,
bool is_incoming, std::optional<std::string> full_name, bool is_known,
std::optional<std::string> device_id, bool for_self_share)
absl::string_view device_id, bool for_self_share)
: device_name(std::move(device_name)),
image_url(std::move(image_url)),
type(type),
is_incoming(is_incoming),
full_name(std::move(full_name)),
is_known(is_known),
device_id(std::move(device_id)),
device_id(device_id),
for_self_share(for_self_share) {
id = ++kLastGeneratedId;
}
@@ -75,9 +76,7 @@ std::string ShareTarget::ToString() const {
if (image_url) {
fmt.push_back(absl::StrFormat("image_url: %s", image_url->GetUrlPath()));
}
if (device_id) {
fmt.push_back(absl::StrFormat("device_id: %s", *device_id));
}
fmt.push_back(absl::StrFormat("device_id: %s", device_id));
fmt.push_back(absl::StrFormat("is_known: %d", is_known));
fmt.push_back(absl::StrFormat("is_incoming: %d", is_incoming));
fmt.push_back(absl::StrFormat("for_self_share: %d", for_self_share));
+3 -2
View File
@@ -19,6 +19,7 @@
#include <optional>
#include <string>
#include "absl/strings/string_view.h"
#include "internal/network/url.h"
#include "sharing/common/nearby_share_enums.h"
@@ -33,7 +34,7 @@ struct ShareTarget {
std::string device_name, ::nearby::network::Url image_url,
ShareTargetType type,
bool is_incoming, std::optional<std::string> full_name, bool is_known,
std::optional<std::string> device_id, bool for_self_share);
absl::string_view device_id, bool for_self_share);
ShareTarget(const ShareTarget&);
ShareTarget(ShareTarget&&);
ShareTarget& operator=(const ShareTarget&);
@@ -54,7 +55,7 @@ struct ShareTarget {
// True if the local device has the PublicCertificate this target is
// advertising.
bool is_known = false;
std::optional<std::string> device_id;
std::string device_id;
// True if the remote device is also owned by the current user.
bool for_self_share = false;
// Vendor ID of the target. This can change over the lifetime of the target.
+2 -2
View File
@@ -47,8 +47,8 @@ std::vector<ShareTargetToStringTestData> GetTestData() {
kShareTargetToStringTestData =
new std::vector<ShareTargetToStringTestData>({
{share_target1,
"ShareTarget<id: 1, type: 0, device_name: , is_known: 0, "
"is_incoming: 0, for_self_share: 0, vendor_id: 0, "
"ShareTarget<id: 1, type: 0, device_name: , device_id: , "
"is_known: 0, is_incoming: 0, for_self_share: 0, vendor_id: 0, "
"receive_disabled: 0>"},
{share_target2,
"ShareTarget<id: 2, type: 1, device_name: test_name, full_name: "
+6 -8
View File
@@ -31,8 +31,7 @@
#include "sharing/common/nearby_share_enums.h"
#include "sharing/proto/wire_format.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
namespace {
using ::location::nearby::proto::sharing::AttachmentSourceType;
@@ -128,8 +127,8 @@ TextAttachment::TextAttachment(Type type, std::string text_body,
text_title_(text_title.has_value() && !text_title->empty()
? *text_title
: GetTextTitle(text_body, type)),
text_body_(std::move(text_body)),
mime_type_(mime_type ? *mime_type : std::string()) {}
mime_type_(mime_type.value_or("")),
text_body_(std::move(text_body)) {}
TextAttachment::TextAttachment(int64_t id, Type type, std::string text_title,
int64_t size, int32_t batch_id,
@@ -145,8 +144,8 @@ TextAttachment::TextAttachment(int64_t id, Type type, std::string text_body,
: Attachment(id, Attachment::Family::kText, size, batch_id, source_type),
type_(type),
text_title_(std::move(text_title)),
text_body_(std::move(text_body)),
mime_type_(std::move(mime_type)) {}
mime_type_(std::move(mime_type)),
text_body_(std::move(text_body)) {}
absl::string_view TextAttachment::GetDescription() const { return text_title_; }
@@ -176,5 +175,4 @@ void TextAttachment::set_text_body(std::string text_body) {
text_title_ = GetTextTitle(text_body_, type_);
}
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
+5 -8
View File
@@ -25,8 +25,7 @@
#include "sharing/common/nearby_share_enums.h"
#include "sharing/proto/wire_format.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
// Represents a text attachment.
class TextAttachment : public Attachment {
@@ -49,8 +48,7 @@ class TextAttachment : public Attachment {
location::nearby::proto::sharing::AttachmentSourceType source_type);
TextAttachment(const TextAttachment&) = default;
TextAttachment(TextAttachment&&) = default;
TextAttachment& operator=(const TextAttachment&) = default;
TextAttachment& operator=(TextAttachment&&) = default;
TextAttachment& operator=(TextAttachment&&) = delete;
~TextAttachment() override = default;
absl::string_view text_body() const { return text_body_; }
@@ -66,13 +64,12 @@ class TextAttachment : public Attachment {
std::string mime_type() const { return mime_type_; }
private:
Type type_ = service::proto::TextMetadata::UNKNOWN;
const Type type_;
std::string text_title_;
const std::string mime_type_;
std::string text_body_;
std::string mime_type_;
};
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
#endif // THIRD_PARTY_NEARBY_SHARING_TEXT_ATTACHMENT_H_
+10 -10
View File
@@ -35,16 +35,16 @@ class TransferMetadata {
kAwaitingLocalConfirmation,
kAwaitingRemoteAcceptance,
kInProgress,
kComplete,
kFailed,
kRejected,
kCancelled,
kTimedOut,
kMediaUnavailable,
kNotEnoughSpace,
kUnsupportedAttachmentType,
kDeviceAuthenticationFailed,
kIncompletePayloads,
kComplete, // final
kFailed, // final
kRejected, // final
kCancelled, // final
kTimedOut, // final
kMediaUnavailable, // final
kNotEnoughSpace, // final
kUnsupportedAttachmentType, // final
kDeviceAuthenticationFailed, // final
kIncompletePayloads, // final
kMaxValue = kIncompletePayloads
};
// LINT.ThenChange(//depot/google3/location/nearby/cpp/sharing/clients/dart/platform/lib/types/transfer_status.dart)
+5 -10
View File
@@ -23,20 +23,16 @@
#include "sharing/attachment.h"
#include "sharing/common/nearby_share_enums.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
using ::location::nearby::proto::sharing::AttachmentSourceType;
WifiCredentialsAttachment::WifiCredentialsAttachment(
std::string ssid, SecurityType security_type, std::string password,
bool is_hidden, int32_t batch_id, AttachmentSourceType source_type)
: Attachment(Attachment::Family::kWifiCredentials, ssid.size(), batch_id,
source_type),
ssid_(ssid),
security_type_(security_type),
password_(std::move(password)),
is_hidden_(is_hidden) {}
: WifiCredentialsAttachment(/*id=*/0, ssid, security_type,
std::move(password), is_hidden, batch_id,
source_type) {}
WifiCredentialsAttachment::WifiCredentialsAttachment(
int64_t id, std::string ssid, SecurityType security_type,
@@ -65,5 +61,4 @@ void WifiCredentialsAttachment::set_is_hidden(bool is_hidden) {
is_hidden_ = is_hidden;
}
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
+6 -10
View File
@@ -24,9 +24,8 @@
#include "sharing/common/nearby_share_enums.h"
#include "sharing/proto/wire_format.pb.h"
namespace nearby {
namespace sharing {
namespace nearby::sharing {
\
// Represents a WiFi credentials attachment.
class WifiCredentialsAttachment : public Attachment {
public:
@@ -45,9 +44,7 @@ class WifiCredentialsAttachment : public Attachment {
location::nearby::proto::sharing::ATTACHMENT_SOURCE_UNKNOWN);
WifiCredentialsAttachment(const WifiCredentialsAttachment&) = default;
WifiCredentialsAttachment(WifiCredentialsAttachment&&) = default;
WifiCredentialsAttachment& operator=(const WifiCredentialsAttachment&) =
default;
WifiCredentialsAttachment& operator=(WifiCredentialsAttachment&&) = default;
WifiCredentialsAttachment& operator=(WifiCredentialsAttachment&&) = delete;
~WifiCredentialsAttachment() override = default;
absl::string_view ssid() const { return ssid_; }
@@ -63,13 +60,12 @@ class WifiCredentialsAttachment : public Attachment {
void set_is_hidden(bool is_hidden);
private:
std::string ssid_;
SecurityType security_type_;
const std::string ssid_;
const SecurityType security_type_;
std::string password_;
bool is_hidden_;
};
} // namespace sharing
} // namespace nearby
} // namespace nearby::sharing
#endif // THIRD_PARTY_NEARBY_SHARING_WIFI_CREDENTIALS_ATTACHMENT_H_
+3 -3
View File
@@ -58,7 +58,7 @@ class WorkerQueue {
}
callback_ = std::move(callback);
{
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
if (!queue_.empty()) {
ScheduleCallback();
}
@@ -78,7 +78,7 @@ class WorkerQueue {
// Queues an item to be processed by the callback.
// Callback are edge triggered.
void Queue(T item) {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
queue_.push(std::move(item));
ScheduleCallback();
}
@@ -88,7 +88,7 @@ class WorkerQueue {
// scheduled when new items are queued.
std::queue<T> ReadAll() {
is_scheduled_ = false;
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
std::queue<T> queue;
queue.swap(queue_);
return queue;