Merge remote-tracking branch 'nearby/main'

# Conflicts:
#	connections/implementation/bwu_manager_test.cc
#	sharing/BUILD
#	sharing/certificates/fake_nearby_share_certificate_manager.cc
#	sharing/certificates/fake_nearby_share_certificate_manager.h
#	sharing/internal/base/utf_string_conversions.h
This commit is contained in:
Lasan Mahaliyana
2026-07-26 22:46:37 +05:30
155 changed files with 5257 additions and 2018 deletions
+5
View File
@@ -250,6 +250,7 @@ cc_library(
"//internal/base:files",
"//internal/platform:types",
"//location/nearby/sharing/lib/sync:sync_manager",
"//location/nearby/cpp/sharing/clients/cpp/common",
"//proto:sharing_enums_cc_proto",
"//sharing/analytics",
"//sharing/certificates",
@@ -393,6 +394,7 @@ cc_library(
"//connections/implementation/analytics:analytics_recorder_impl",
"//internal/base",
"//internal/base:file_path",
"//internal/base:files",
"//internal/flags:nearby_flags",
"//internal/network:url",
"//internal/platform:base",
@@ -402,6 +404,7 @@ cc_library(
"//internal/platform:types",
"//internal/platform/implementation:types",
#"//location/nearby/analytics/cpp/logging:event_logger",
"//location/nearby/cpp/sharing/clients/cpp/common",
"//location/nearby/sharing/lib/account:account_manager",
"//location/nearby/sharing/lib/rpc:grpc_async_client_factory",
"//location/nearby/sharing/lib/rpc:sharing_rpc_client",
@@ -425,6 +428,7 @@ cc_library(
"//sharing/proto:share_cc_proto",
"//sharing/proto:wire_format_cc_proto",
"//sharing/scheduling",
"//third_party/gloop/util/time:protoutil",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/container:flat_hash_map",
@@ -655,6 +659,7 @@ cc_test(
":transfer_metadata",
":transfer_metadata_matchers",
":types",
"//google/protobuf:timestamp_cc_proto",
"//internal/base:file_path",
"//internal/base:files",
"//internal/flags:nearby_flags",
+6 -4
View File
@@ -111,7 +111,9 @@ class AnalyticsRecorder {
virtual void NewReceiveIntroduction(
int64_t session_id, const ShareTarget& share_target,
std::optional<std::string> referrer_package,
location::nearby::proto::sharing::OSType share_target_os_type) = 0;
location::nearby::proto::sharing::OSType share_target_os_type,
location::nearby::proto::sharing::SharingUseCase sharing_use_case,
location::nearby::proto::sharing::PowerStatus power_status) = 0;
virtual void NewRespondToIntroduction(
location::nearby::proto::sharing::ResponseToIntroduction action,
@@ -142,8 +144,7 @@ class AnalyticsRecorder {
const AttachmentContainer& attachments,
int transfer_position,
int concurrent_connections,
bool advanced_protection_enabled,
bool advanced_protection_mismatch) = 0;
bool advanced_protection_enabled) = 0;
virtual void NewSendFastInitialization() = 0;
@@ -159,7 +160,8 @@ class AnalyticsRecorder {
virtual void NewSendIntroduction(
int64_t session_id, const ShareTarget& share_target,
int transfer_position, int concurrent_connections,
location::nearby::proto::sharing::OSType share_target_os_type) = 0;
location::nearby::proto::sharing::OSType share_target_os_type,
location::nearby::proto::sharing::PowerStatus power_status) = 0;
virtual void NewSetVisibility(
nearby::sharing::proto::DeviceVisibility src_visibility,
+4
View File
@@ -63,8 +63,11 @@ cc_library(
"//sharing/proto:enums_cc_proto",
"//sharing/proto:share_cc_proto",
"//sharing/scheduling",
"//third_party/gloop/util/time:protoutil",
"//util/hash:highway_fingerprint",
"@com_google_absl//absl/algorithm",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/container:flat_hash_map",
@@ -145,6 +148,7 @@ cc_test(
"//sharing/proto:share_cc_proto",
"//sharing/scheduling",
"//sharing/scheduling:test_support",
"//third_party/gloop/util/time:protoutil",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/status",
@@ -20,9 +20,11 @@
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "internal/base/file_path.h"
#include "sharing/certificates/nearby_share_certificate_manager.h"
#include "sharing/certificates/nearby_share_encrypted_metadata_key.h"
@@ -102,6 +104,12 @@ void FakeNearbyShareCertificateManager::ClearPublicCertificates(
callback(true);
}
void FakeNearbyShareCertificateManager::AddBindingToPublicCertificate(
absl::string_view certificate_id, absl::string_view binding_id) {
add_binding_to_public_certificate_calls_.push_back(
{std::string(certificate_id), std::string(binding_id)});
}
std::optional<NearbySharePrivateCertificate>
FakeNearbyShareCertificateManager::GetValidPrivateCertificate(
DeviceVisibility visibility) const {
@@ -24,6 +24,7 @@
#include <string>
#include <vector>
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "sharing/certificates/nearby_share_certificate_manager.h"
#include "sharing/certificates/nearby_share_certificate_manager_impl.h"
@@ -89,6 +90,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
CertDecryptedCallback callback;
};
struct AddBindingToPublicCertificateCall {
std::string certificate_id;
std::string binding_id;
};
FakeNearbyShareCertificateManager();
~FakeNearbyShareCertificateManager() override;
@@ -100,6 +106,13 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
void ForceUploadPrivateCertificates() override {};
void ClearPublicCertificates(std::function<void(bool)> callback) override;
void SetVendorId(int32_t vendor_id) override {}
void AddBindingToPublicCertificate(
absl::string_view certificate_id, absl::string_view binding_id) override;
void SetJoinBindingTime(absl::Time join_binding_time,
absl::Duration life_time) override {
join_binding_time_ = join_binding_time;
join_binding_life_time_ = life_time;
}
std::string Dump() const override { return ""; }
// Make protected methods from base class public in this fake class.
@@ -125,6 +138,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
return get_decrypted_public_certificate_calls_;
}
const std::vector<AddBindingToPublicCertificateCall>&
add_binding_to_public_certificate_calls() const {
return add_binding_to_public_certificate_calls_;
}
private:
// NearbyShareCertificateManager:
void OnStartScheduledTasks() override {}
@@ -139,7 +157,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
size_t num_clear_public_certificates_calls_ = 0;
std::vector<GetDecryptedPublicCertificateCall>
get_decrypted_public_certificate_calls_;
std::vector<AddBindingToPublicCertificateCall>
add_binding_to_public_certificate_calls_;
std::vector<uint8_t> next_salt_;
absl::Time join_binding_time_;
absl::Duration join_binding_life_time_;
};
} // namespace sharing
@@ -106,7 +106,16 @@ void FakeNearbyShareCertificateStorage::GetPublicCertificate(
std::function<
void(bool, std::unique_ptr<nearby::sharing::proto::PublicCertificate>)>
callback) {
get_public_certificate_callback_ = std::move(callback);
get_public_certificate_callback_ = callback;
if (is_sync_mode_) {
for (const auto& cert : public_certificates_) {
if (cert.secret_id() == id) {
callback(true, std::make_unique<PublicCertificate>(cert));
return;
}
}
callback(false, nullptr);
}
}
std::vector<NearbySharePrivateCertificate>
@@ -135,6 +144,19 @@ void FakeNearbyShareCertificateStorage::AddPublicCertificates(
public_certificates.end()),
callback);
if (is_sync_mode_) {
for (const auto& cert : public_certificates) {
bool found = false;
for (auto& existing_cert : public_certificates_) {
if (existing_cert.secret_id() == cert.secret_id()) {
existing_cert = cert;
found = true;
break;
}
}
if (!found) {
public_certificates_.push_back(cert);
}
}
callback(add_public_certificates_result_);
}
}
@@ -152,6 +174,12 @@ void FakeNearbyShareCertificateStorage::ClearPublicCertificates(
clear_public_certificates_callbacks_.push_back(std::move(callback));
}
void FakeNearbyShareCertificateStorage::SetPublicCertificates(
absl::Span<const PublicCertificate> public_certificates) {
public_certificates_ = std::vector<PublicCertificate>(
public_certificates.begin(), public_certificates.end());
}
void FakeNearbyShareCertificateStorage::SetPublicCertificateIds(
absl::Span<const absl::string_view> ids) {
public_certificate_ids_ = std::vector<std::string>(ids.begin(), ids.end());
@@ -123,6 +123,9 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
void ClearPublicCertificates(ResultCallback callback) override;
void SetPublicCertificateIds(absl::Span<const absl::string_view> ids);
void SetPublicCertificates(
absl::Span<const nearby::sharing::proto::PublicCertificate>
public_certificates);
void SetNextPublicCertificateExpirationTime(absl::Time time);
std::vector<PublicCertificateCallback>& get_public_certificates_callbacks() {
@@ -156,6 +159,7 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
absl::Mutex mutex_;
absl::Time next_public_certificate_expiration_time_ = absl::InfiniteFuture();
std::vector<std::string> public_certificate_ids_;
std::vector<nearby::sharing::proto::PublicCertificate> public_certificates_;
std::vector<NearbySharePrivateCertificate> private_certificates_
ABSL_GUARDED_BY(mutex_);
std::vector<PublicCertificateCallback> get_public_certificates_callbacks_;
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <optional>
#include <string>
#include <vector>
#include "absl/types/span.h"
@@ -73,6 +74,15 @@ NearbyShareCertificateManager::EncryptPrivateCertificateMetadataKey(
return encrypted_key;
}
std::optional<std::string>
NearbyShareCertificateManager::GetPrivateCertificateId(
DeviceVisibility visibility) {
std::optional<NearbySharePrivateCertificate> cert =
GetValidPrivateCertificate(visibility);
if (!cert) return std::nullopt;
return std::string(cert->id().begin(), cert->id().end());
}
std::optional<std::vector<uint8_t>>
NearbyShareCertificateManager::SignWithPrivateCertificate(
DeviceVisibility visibility, absl::Span<const uint8_t> payload) const {
@@ -22,6 +22,8 @@
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "internal/base/observer_list.h"
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
@@ -80,6 +82,12 @@ class NearbyShareCertificateManager {
std::optional<NearbyShareEncryptedMetadataKey>
EncryptPrivateCertificateMetadataKey(proto::DeviceVisibility visibility);
// Returns the id of the currently valid private certificate with
// |visibility|, or absl::nullopt if there is no valid private certificate
// with |visibility|.
std::optional<std::string> GetPrivateCertificateId(
proto::DeviceVisibility visibility);
// Signs the input |payload| using the currently valid private certificate
// with |visibility|. Returns absl::nullopt if there is no valid private
// certificate with |visibility| or if the signing was unsuccessful.
@@ -119,9 +127,18 @@ class NearbyShareCertificateManager {
// Sets the vendor ID to generate certificates for.
virtual void SetVendorId(int32_t vendor_id) = 0;
// Sets the timestamp of the join binding rpc. This is used to ensure that the
// requested public certificates contain the ids of the binding.
// `life_time` determines how long this join_binding_time will be used.
virtual void SetJoinBindingTime(absl::Time join_binding_time,
absl::Duration life_time) = 0;
// Dump certificates ID information for troubleshooting.
virtual std::string Dump() const = 0;
virtual void AddBindingToPublicCertificate(
absl::string_view certificate_id, absl::string_view binding_id) = 0;
protected:
virtual void OnStartScheduledTasks() = 0;
virtual void OnStopScheduledTasks() = 0;
@@ -34,6 +34,7 @@
#include "location/nearby/sharing/lib/account/account_manager.h"
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
#include "absl/algorithm/algorithm.h"
#include "absl/algorithm/container.h"
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
@@ -41,9 +42,11 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/synchronization/notification.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "third_party/gloop/util/time/protoutil.h"
#include "internal/base/file_path.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/mac_address.h"
@@ -383,6 +386,13 @@ void NearbyShareCertificateManagerImpl::CertificateDownloadContext::
page_number_++;
QuerySharedCredentialsWithBindingIdsRequest request;
request.set_name(absl::StrCat("devices/", device_id_));
if (join_time_.has_value()) {
absl::StatusOr<google::protobuf::Timestamp> join_time =
util_time::EncodeGoogleApiProto(*join_time_);
if (join_time.ok()) {
*request.mutable_join_binding_time() = *join_time;
}
}
if (next_page_token_.has_value()) {
request.set_page_token(*next_page_token_);
}
@@ -408,7 +418,8 @@ void NearbyShareCertificateManagerImpl::CertificateDownloadContext::
<< absl::BytesToHexString(credential.data());
continue;
}
VLOG(1) << "Successfully parsed credential: " << credential.id();
VLOG(1) << "Successfully parsed credential: " << credential.id()
<< " with binding id: " << certificate.binding_id();
certificates_.push_back(certificate);
}
@@ -466,10 +477,20 @@ bool NearbyShareCertificateManagerImpl::DownloadPublicCertificatesInExecutor() {
return true;
}
// Clear join_time if it is expired.
std::optional<absl::Time> join_time;
{
absl::MutexLock lock(join_time_mutex_);
if (join_time_.has_value() &&
context_->GetClock()->Now() > join_time_discard_time_) {
join_time_.reset();
}
join_time = join_time_;
}
bool download_succeeded = false;
absl::Notification notification;
auto context = std::make_unique<CertificateDownloadContext>(
nearby_identity_client_, std::move(device_id),
nearby_identity_client_, std::move(device_id), join_time,
[this, &download_succeeded, &notification](
absl::StatusOr<std::vector<PublicCertificate>> certificates_status) {
if (!certificates_status.ok()) {
@@ -489,7 +510,7 @@ bool NearbyShareCertificateManagerImpl::DownloadPublicCertificatesInExecutor() {
notification.Notify();
});
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::kEnableFileSync)) {
config_package_nearby::nearby_sharing_feature::kEnableBackup)) {
context->QuerySharedCredentialsWithBindingIdsFetchNextPage();
} else {
context->QuerySharedCredentialsFetchNextPage();
@@ -744,6 +765,13 @@ void NearbyShareCertificateManagerImpl::SetVendorId(int32_t vendor_id) {
RegeneratePrivateCertificates();
}
void NearbyShareCertificateManagerImpl::SetJoinBindingTime(
absl::Time join_binding_time, absl::Duration life_time) {
absl::MutexLock lock(join_time_mutex_);
join_time_ = join_binding_time;
join_time_discard_time_ = context_->GetClock()->Now() + life_time;
}
std::string NearbyShareCertificateManagerImpl::Dump() const {
std::stringstream sstream;
sstream << "Public Certificates" << std::endl;
@@ -892,6 +920,32 @@ bool NearbyShareCertificateManagerImpl::RefreshPrivateCertificatesInExecutor(
return true;
}
void NearbyShareCertificateManagerImpl::AddBindingToPublicCertificate(
absl::string_view certificate_id, absl::string_view binding_id) {
LOG(INFO) << "Adding binding to public certificate: "
<< absl::BytesToHexString(certificate_id);
absl::Notification notification;
certificate_storage_->GetPublicCertificate(
certificate_id,
[this, id = std::string(binding_id), &notification](
bool success, std::unique_ptr<PublicCertificate> certificate) {
if (success && certificate != nullptr) {
certificate->set_binding_id(id);
certificate_storage_->AddPublicCertificates(
{*certificate}, [](bool success) {
if (!success) {
LOG(WARNING)
<< "Failed to add binding to public certificate.";
}
});
} else {
LOG(WARNING) << "Failed to add binding to public certificate.";
}
notification.Notify();
});
notification.WaitForNotification();
}
void NearbyShareCertificateManagerImpl::ForceUploadPrivateCertificates() {
executor_->PostTask([this]() {
private_certificate_expiration_scheduler_->HandleResult(
@@ -942,9 +996,9 @@ bool NearbyShareCertificateManagerImpl::UpdateAccountInfoInExecutor() {
get_account_info_succeeded = true;
const auto& capabilities = response->account_info().capabilities();
bool has_titanium_capability =
(std::find(capabilities.begin(), capabilities.end(),
google::nearby::identity::v1::AccountInfo::
CAPABILITY_TITANIUM) != capabilities.end());
(absl::c_find(capabilities,
google::nearby::identity::v1::AccountInfo::
CAPABILITY_TITANIUM) != capabilities.end());
preference_manager_.SetBoolean(PrefNames::kAdvancedProtectionEnabled,
has_titanium_capability);
LOG(INFO) << "GetAccountInfo succeeded, advanced protection enabled: "
@@ -26,8 +26,11 @@
#include "location/nearby/sharing/lib/account/account_manager.h"
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "internal/base/file_path.h"
#include "internal/platform/task_runner.h"
@@ -92,7 +95,12 @@ class NearbyShareCertificateManagerImpl
void ForceUploadPrivateCertificates() override;
void ClearPublicCertificates(std::function<void(bool)> callback) override;
void SetVendorId(int32_t vendor_id) override;
void SetJoinBindingTime(absl::Time join_binding_time,
absl::Duration life_time)
ABSL_LOCKS_EXCLUDED(join_time_mutex_) override;
std::string Dump() const override;
void AddBindingToPublicCertificate(
absl::string_view certificate_id, absl::string_view binding_id) override;
private:
// Class for maintaining a single instance of public certificate download
@@ -104,12 +112,14 @@ class NearbyShareCertificateManagerImpl
nearby::sharing::api::IdentityRpcClient* absl_nonnull
nearby_identity_client,
std::string device_id,
std::optional<absl::Time> join_time,
absl::AnyInvocable<void(absl::StatusOr<std::vector<
nearby::sharing::proto::PublicCertificate>>
certificates_status) &&>
download_callback)
: nearby_identity_client_(nearby_identity_client),
device_id_(std::move(device_id)),
join_time_(join_time),
download_callback_(std::move(download_callback)) {}
// Fetches the next page of certificates by calling Identity API
@@ -123,7 +133,8 @@ class NearbyShareCertificateManagerImpl
private:
nearby::sharing::api::IdentityRpcClient* absl_nonnull const
nearby_identity_client_;
std::string device_id_;
const std::string device_id_;
const std::optional<absl::Time> join_time_;
std::optional<std::string> next_page_token_;
int page_number_ = 1;
std::vector<nearby::sharing::proto::PublicCertificate> certificates_;
@@ -219,6 +230,12 @@ class NearbyShareCertificateManagerImpl
account_info_update_scheduler_;
std::unique_ptr<TaskRunner> executor_;
absl::Mutex join_time_mutex_;
// Set to the transaction timestamp of the last successful pairing if
// available. This is returned from the phone in the BindingResponse message.
std::optional<absl::Time> join_time_ ABSL_GUARDED_BY(join_time_mutex_);
// The time when the join_time_ will be discarded.
absl::Time join_time_discard_time_ ABSL_GUARDED_BY(join_time_mutex_);
};
} // namespace nearby::sharing
@@ -39,6 +39,7 @@
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "third_party/gloop/util/time/protoutil.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/mac_address.h"
#include "sharing/certificates/constants.h"
@@ -78,6 +79,7 @@ using ::google::nearby::identity::v1::
QuerySharedCredentialsWithBindingIdsResponse;
using ::nearby::sharing::proto::DeviceVisibility;
using ::nearby::sharing::proto::PublicCertificate;
using ::protobuf_matchers::EqualsProto;
using ::testing::Not;
using ::testing::ReturnRef;
using ::testing::UnorderedElementsAreArray;
@@ -634,6 +636,31 @@ TEST_F(NearbyShareCertificateManagerImplTest,
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS));
}
TEST_F(NearbyShareCertificateManagerImplTest,
GetPrivateCertificateIdWithNoCertificates) {
Initialize();
cert_store_->ReplacePrivateCertificates({});
EXPECT_FALSE(cert_manager_->GetPrivateCertificateId(
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value());
}
TEST_F(NearbyShareCertificateManagerImplTest,
GetPrivateCertificateIdWithValidCertificate) {
Initialize();
NearbySharePrivateCertificate private_certificate =
GetNearbyShareTestPrivateCertificate(
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS);
cert_store_->ReplacePrivateCertificates({private_certificate});
FastForward(GetNearbyShareTestNotBefore() +
kNearbyShareCertificateValidityPeriod * 0.5 - Now());
ASSERT_TRUE(cert_manager_->GetPrivateCertificateId(
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value());
EXPECT_EQ(cert_manager_->GetPrivateCertificateId(
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).value(),
std::string(private_certificate.id().begin(),
private_certificate.id().end()));
}
TEST_F(NearbyShareCertificateManagerImplTest, SignWithPrivateCertificate) {
Initialize();
NearbySharePrivateCertificate private_certificate =
@@ -782,7 +809,7 @@ TEST_F(NearbyShareCertificateManagerImplTest,
TEST_F(NearbyShareCertificateManagerImplTest,
QuerySharedCredentialsWithBindingIdsSuccess) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_sharing_feature::kEnableFileSync, true);
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
Initialize();
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
@@ -791,12 +818,48 @@ TEST_F(NearbyShareCertificateManagerImplTest,
TEST_F(NearbyShareCertificateManagerImplTest,
QuerySharedCredentialsWithBindingIdsRPCFailure) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_sharing_feature::kEnableFileSync, true);
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
Initialize();
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
/*num_pages=*/2, DownloadPublicCertificatesResult::kHttpError));
}
TEST_F(NearbyShareCertificateManagerImplTest,
QuerySharedCredentialsWithBindingIdsWithJoinTime) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
Initialize();
cert_manager_->SetJoinBindingTime(absl::FromUnixSeconds(123456789),
absl::Seconds(30));
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
std::vector<QuerySharedCredentialsWithBindingIdsRequest> requests =
identity_client_.query_shared_credentials_with_binding_ids_requests();
for (const auto& request : requests) {
ASSERT_OK_AND_ASSIGN(
auto expected_time,
util_time::EncodeGoogleApiProto(absl::FromUnixSeconds(123456789)));
EXPECT_THAT(request.join_binding_time(), EqualsProto(expected_time));
}
}
TEST_F(NearbyShareCertificateManagerImplTest,
QuerySharedCredentialsWithBindingIdsWithJoinTimeExpiration) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
Initialize();
cert_manager_->SetJoinBindingTime(absl::FromUnixSeconds(123456789),
absl::Seconds(30));
FastForward(absl::Seconds(31));
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
std::vector<QuerySharedCredentialsWithBindingIdsRequest> requests =
identity_client_.query_shared_credentials_with_binding_ids_requests();
for (const auto& request : requests) {
EXPECT_FALSE(request.has_join_binding_time());
}
}
TEST_F(NearbyShareCertificateManagerImplTest, ClearPublicCertificates) {
Initialize();
cert_manager_->ClearPublicCertificates([&](bool result) {});
@@ -1110,4 +1173,24 @@ TEST_F(NearbyShareCertificateManagerImplTest,
PrefNames::kAdvancedProtectionEnabled, /*default_value=*/false));
}
TEST_F(NearbyShareCertificateManagerImplTest, AddBindingToPublicCertificate) {
Initialize();
PublicCertificate cert;
cert.set_secret_id("test_cert_id");
cert.set_binding_id("old_binding_id");
cert_store_->SetPublicCertificates({cert});
cert_store_->SetAddPublicCertificatesResult(true);
cert_manager_->AddBindingToPublicCertificate("test_cert_id",
"new_binding_id");
ASSERT_EQ(cert_store_->add_public_certificates_calls().size(), 1u);
const auto& call = cert_store_->add_public_certificates_calls().back();
ASSERT_EQ(call.public_certificates.size(), 1u);
EXPECT_EQ(call.public_certificates[0].secret_id(), "test_cert_id");
EXPECT_EQ(call.public_certificates[0].binding_id(), "new_binding_id");
}
} // namespace nearby::sharing
@@ -342,7 +342,8 @@ void NearbyShareCertificateStorageImpl::GetPublicCertificate(
});
return;
}
VLOG(1) << __func__ << ": Calling LoadCertificate on database, key: " << id;
VLOG(1) << __func__ << ": Calling LoadCertificate on database, key: "
<< absl::BytesToHexString(id);
public_certificate_database_->LoadCertificate(id, std::move(callback));
}
@@ -211,20 +211,20 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeRetrySucceed) {
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
MockPublicCertificateDb* mock_db = db.get();
EXPECT_CALL(*mock_db, Initialize(_))
.WillOnce(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
.WillOnce(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kError);
}))
.WillRepeatedly(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
})
.WillRepeatedly(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kOk);
}));
});
EXPECT_CALL(*mock_db, Destroy(_))
.WillOnce(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
.WillOnce([](absl::AnyInvocable<void(bool) &&> callback) {
std::move(callback)(true);
}));
});
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
preference_manager_, std::move(db));
@@ -243,11 +243,11 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeRetryFailed) {
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
MockPublicCertificateDb* mock_db = db.get();
EXPECT_CALL(*mock_db, Initialize(_))
.WillRepeatedly(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
.WillRepeatedly(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kError);
}));
});
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
preference_manager_, std::move(db));
@@ -267,23 +267,23 @@ TEST_F(NearbyShareCertificateStorageImplTest,
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
MockPublicCertificateDb* mock_db = db.get();
EXPECT_CALL(*mock_db, Initialize(_))
.WillOnce(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
.WillOnce(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kCorrupt);
}))
.WillRepeatedly(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
})
.WillRepeatedly(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kOk);
}));
});
// Destroy called once from corrupted initialization and once from cal to
// ClearPublicCertificates.
EXPECT_CALL(*mock_db, Destroy(_))
.Times(2)
.WillRepeatedly(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
.WillRepeatedly([](absl::AnyInvocable<void(bool) &&> callback) {
std::move(callback)(true);
}));
});
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
preference_manager_, std::move(db));
@@ -301,15 +301,15 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeCorruptDestroyFails) {
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
MockPublicCertificateDb* mock_db = db.get();
EXPECT_CALL(*mock_db, Initialize(_))
.WillOnce(Invoke(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
.WillOnce(
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) {
std::move(callback)(MockPublicCertificateDb::InitStatus::kCorrupt);
}));
});
EXPECT_CALL(*mock_db, Destroy(_))
.WillOnce(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
.WillOnce([](absl::AnyInvocable<void(bool) &&> callback) {
std::move(callback)(false);
}));
});
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
preference_manager_, std::move(db));
@@ -333,18 +333,18 @@ TEST_F(NearbyShareCertificateStorageImplTest, DeferredCallbackQueue) {
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
MockPublicCertificateDb* mock_db = db.get();
EXPECT_CALL(*mock_db, Initialize(_))
.WillOnce(Invoke(
[&](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
callback) { init_status_callback = std::move(callback); }));
.WillOnce(
[&](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
callback) { init_status_callback = std::move(callback); });
EXPECT_CALL(*mock_db, Destroy(_))
.WillOnce(Invoke([&](absl::AnyInvocable<void(bool)&&> callback) {
.WillOnce([&](absl::AnyInvocable<void(bool) &&> callback) {
destroy_callback = std::move(callback);
}));
});
EXPECT_CALL(*mock_db, LoadEntries(_))
.WillOnce(Invoke(
.WillOnce(
[&](absl::AnyInvocable<void(
bool, std::unique_ptr<std::vector<PublicCertificate>>)&&>
callback) { load_callback = std::move(callback); }));
bool, std::unique_ptr<std::vector<PublicCertificate>>) &&>
callback) { load_callback = std::move(callback); });
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
preference_manager_, std::move(db));
+1
View File
@@ -67,6 +67,7 @@ void RegisterNearbySharingPrefs(PreferenceManager& preference_manager,
preference_manager.Remove(PrefNames::kUsers);
preference_manager.SetBoolean(PrefNames::kAdvancedProtectionEnabled, false);
preference_manager.RemoveAllSyncConfigs();
preference_manager.RemoveAllBindingConfigs();
}
@@ -61,9 +61,9 @@ constexpr auto kShowAutoUpdateSetting =
// The default time in milliseconds a cached entry can be in LOST state.
constexpr auto kDiscoveryCacheLostExpiryMs =
flags::Flag<int64_t>(kConfigPackage, "45658774", 15000);
// When true, enable file sync feature.
constexpr auto kEnableFileSync =
flags::Flag<bool>(kConfigPackage, "45762616", false);
// When true, enable suspend resume listener.
constexpr auto kEnableSuspendResumeListener =
flags::Flag<bool>(kConfigPackage, "45815625", false);
// When true, enable wifi hotspot medium for HP Realtek devices.
constexpr auto kEnableWifiHotspotForHpRealtekDevices =
flags::Flag<bool>(kConfigPackage, "45673628", false);
@@ -108,7 +108,7 @@ inline absl::btree_map<int, const flags::Flag<bool>&> GetBoolFlags() {
{45411589, kEnableRetryResumeTransfer},
{45459748, kEnableSendingDesktopEvents},
{45409033, kShowAutoUpdateSetting},
{45762616, kEnableFileSync},
{45815625, kEnableSuspendResumeListener},
{45673628, kEnableWifiHotspotForHpRealtekDevices},
{45683539, kUseAlternateServiceUuidForDiscovery},
{45776229, kEnableBackup},
+1
View File
@@ -63,6 +63,7 @@ cc_library(
"//internal/platform/implementation:types",
"//location/nearby/sharing/lib/account:account_manager",
"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
"//location/nearby/sharing/lib/sync:sync_config_prefs_cc_proto",
"//sharing/proto:share_cc_proto",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/strings:string_view",
+13 -1
View File
@@ -23,6 +23,7 @@
#include <vector>
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
@@ -80,6 +81,10 @@ class PreferenceManager {
virtual void RemoveDictionaryItem(absl::string_view key,
absl::string_view dictionary_item) = 0;
virtual void SetSyncConfigValue(
absl::string_view binding_id,
const nearby::sharing::sync::SyncConfigPrefs& value) = 0;
virtual void SetSyncBindingValue(
const nearby::sharing::sync::SyncBindingPrefs& value) = 0;
@@ -122,12 +127,19 @@ class PreferenceManager {
virtual std::optional<std::string> GetDictionaryStringValue(
absl::string_view key, absl::string_view dictionary_item) const = 0;
virtual std::optional<nearby::sharing::sync::SyncConfigPrefs>
GetSyncConfigValue(absl::string_view binding_id) const = 0;
virtual void RemoveSyncConfigPref(absl::string_view binding_id) = 0;
virtual std::optional<nearby::sharing::sync::SyncBindingPrefs>
GetSyncBindingValue() const = 0;
// Removes preferences
virtual void Remove(absl::string_view key) = 0;
// Removes all binding configs.
// Removes all sync configs.
// Observers are not notified for each removed config.
virtual void RemoveAllSyncConfigs() = 0; // Removes all binding configs.
// Observers are not notified for each removed config.
virtual void RemoveAllBindingConfigs() = 0;
+10 -2
View File
@@ -58,10 +58,18 @@ class PrefNames {
// Binding configs preferences are stored in pref keys:
// kBindingConfigPrefix + <service_name>
// Example: "nearby_sharing.binding_config.FileSync"
// TODO: b/485304482 - define data format for binding configs.
// For FileSync service, data stored in binding config prefs is a
// nearby::sharing::sync::SyncBindingPrefs proto.
static constexpr absl::string_view kBindingConfigPrefix =
"nearby_sharing.binding_config.";
};
// Sync configs preferences are stored in pref keys:
// kSyncConfigPrefix + <binding ID>
// Example: "nearby_sharing.sync_config.01243347-2343-4324-3423-432432432432"
// Data stored in sync config prefs is a
// nearby::sharing::sync::SyncConfigPrefs proto.
static constexpr absl::string_view kSyncConfigPrefix =
"nearby_sharing.sync_config.";};
} // namespace nearby::sharing
+1
View File
@@ -41,6 +41,7 @@ cc_library(
"//internal/platform:types",
"//internal/test",
"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
"//location/nearby/sharing/lib/sync:sync_config_prefs_cc_proto",
"//sharing/internal/api:platform",
"//sharing/internal/public:pref_names",
"//sharing/internal/public:types",
@@ -23,6 +23,7 @@
#include <vector>
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@@ -36,6 +37,7 @@ namespace nearby {
using ::nearby::sharing::PrefNames;
using ::nearby::sharing::api::PrivateCertificateData;
using ::nearby::sharing::sync::SyncBindingPrefs;
using ::nearby::sharing::sync::SyncConfigPrefs;
// Preference suffix for the sync binding information.
constexpr absl::string_view kFileSyncBindingName = "FileSync";
@@ -243,6 +245,16 @@ void FakePreferenceManager::RemoveDictionaryItem(
NotifyPreferenceChanged(key);
}
void FakePreferenceManager::SetSyncConfigValue(absl::string_view binding_id,
const SyncConfigPrefs& value) {
SetValue(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id),
value.SerializeAsString());
}
void FakePreferenceManager::RemoveSyncConfigPref(absl::string_view binding_id) {
Remove(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id));
}
void FakePreferenceManager::SetSyncBindingValue(
const SyncBindingPrefs& value) {
SetValue(absl::StrCat(PrefNames::kBindingConfigPrefix, kFileSyncBindingName),
@@ -333,6 +345,21 @@ std::optional<std::string> FakePreferenceManager::GetDictionaryStringValue(
return GetDictionaryValue<std::string>(key, dictionary_item);
}
std::optional<SyncConfigPrefs> FakePreferenceManager::GetSyncConfigValue(
absl::string_view binding_id) const {
std::string serialized_sync_config;
serialized_sync_config =
GetString(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id), "");
if (serialized_sync_config.empty()) {
return std::nullopt;
}
SyncConfigPrefs sync_config;
if (!sync_config.ParseFromString(serialized_sync_config)) {
return std::nullopt;
}
return sync_config;
}
std::optional<SyncBindingPrefs> FakePreferenceManager::GetSyncBindingValue()
const {
std::string serialized_sync_binding;
@@ -358,6 +385,13 @@ void FakePreferenceManager::Remove(absl::string_view key) {
NotifyPreferenceChanged(key);
}
void FakePreferenceManager::RemoveAllSyncConfigs() {
absl::MutexLock lock(mutex_);
absl::erase_if(values_, [](const auto& item) {
return item.first.starts_with(PrefNames::kSyncConfigPrefix);
});
}
void FakePreferenceManager::RemoveAllBindingConfigs() {
absl::MutexLock lock(mutex_);
absl::erase_if(values_, [](const auto& item) {
@@ -24,6 +24,7 @@
#include <vector>
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
@@ -75,6 +76,9 @@ class FakePreferenceManager : public nearby::sharing::api::PreferenceManager {
void RemoveDictionaryItem(absl::string_view key,
absl::string_view dictionary_item) override;
void SetSyncConfigValue(
absl::string_view binding_id,
const nearby::sharing::sync::SyncConfigPrefs& value) override;
void SetSyncBindingValue(
const nearby::sharing::sync::SyncBindingPrefs& value) override;
@@ -111,10 +115,14 @@ class FakePreferenceManager : public nearby::sharing::api::PreferenceManager {
absl::string_view key, absl::string_view dictionary_item) const override;
std::optional<std::string> GetDictionaryStringValue(
absl::string_view key, absl::string_view dictionary_item) const override;
std::optional<nearby::sharing::sync::SyncConfigPrefs>
GetSyncConfigValue(absl::string_view binding_id) const override;
void RemoveSyncConfigPref(absl::string_view binding_id) override;
std::optional<nearby::sharing::sync::SyncBindingPrefs>
GetSyncBindingValue() const override;
void Remove(absl::string_view key) override;
void RemoveAllSyncConfigs() override;
void RemoveAllBindingConfigs() override;
void AddObserver(
+11 -7
View File
@@ -821,7 +821,6 @@ void NearbyConnectionsManagerImpl::DeleteUnknownFilePayloadAndCancel(
std::optional<
std::weak_ptr<NearbyConnectionsManagerImpl::PayloadStatusListener>>
NearbyConnectionsManagerImpl::GetStatusListenerForId(int64_t payload_id) const {
MutexLock lock(&mutex_);
auto listener_it = payload_status_listeners_.find(payload_id);
if (listener_it == payload_status_listeners_.end()) {
return std::nullopt;
@@ -840,12 +839,12 @@ NearbyConnectionImpl* NearbyConnectionsManagerImpl::GetConnectionForId(
void NearbyConnectionsManagerImpl::RemoveStatusListenerForPayloadId(
int64_t payload_id) {
MutexLock lock(&mutex_);
payload_status_listeners_.erase(payload_id);
}
void NearbyConnectionsManagerImpl::OnPayloadTransferUpdate(
absl::string_view endpoint_id, const PayloadTransferUpdate& update) {
MutexLock lock(&mutex_);
VLOG(1) << "Received payload transfer update id=" << update.payload_id
<< ",status=" << PayloadStatusToString(update.status)
<< ",total=" << update.total_bytes
@@ -879,16 +878,21 @@ void NearbyConnectionsManagerImpl::OnPayloadTransferUpdate(
// If this is an incoming payload that we have not registered for, then
// we'll treat it as a control frame (e.g. IntroductionFrame) and
// forward it to the associated NearbyConnection.
auto payload = GetIncomingPayload(update.payload_id);
if (payload == nullptr) return;
if (update.status == PayloadStatus::kInProgress) {
return;
}
auto node = incoming_payloads_.extract(update.payload_id);
if (node.empty()) return;
if (update.status != PayloadStatus::kSuccess) return;
NearbyConnectionImpl* connection = GetConnectionForId(endpoint_id);
if (connection == nullptr) return;
auto connection_it = connections_.find(endpoint_id);
if (connection_it == connections_.end()) return;
VLOG(1) << "Writing incoming byte message to NearbyConnection.";
connection->WriteMessage(payload->content.bytes_payload.bytes);
connection_it->second->WriteMessage(
std::move(node.mapped().content.bytes_payload.bytes));
}
void NearbyConnectionsManagerImpl::Reset() {
+2 -2
View File
@@ -128,13 +128,13 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager {
absl::flat_hash_set<FilePath> GetUnknownFilePathsToDelete();
std::optional<std::weak_ptr<PayloadStatusListener>> GetStatusListenerForId(
int64_t payload_id) const ABSL_LOCKS_EXCLUDED(mutex_);
int64_t payload_id) const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
NearbyConnectionImpl* GetConnectionForId(absl::string_view endpoint_id) const
ABSL_LOCKS_EXCLUDED(mutex_);
void RemoveStatusListenerForPayloadId(int64_t payload_id)
ABSL_LOCKS_EXCLUDED(mutex_);
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void Reset();
+204 -27
View File
@@ -31,6 +31,7 @@
#include <utility>
#include <vector>
#include "location/nearby/cpp/sharing/clients/cpp/common/nearby_sharing_common.h"
#include "location/nearby/sharing/lib/account/account_manager.h"
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
@@ -43,8 +44,10 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "third_party/gloop/util/time/protoutil.h"
#include "internal/base/file_path.h"
#include "internal/flags/nearby_flags.h"
#include "internal/network/url.h"
@@ -133,6 +136,17 @@ constexpr absl::Duration kProcessShutdownPendingTimerDelay = // NOLINT
absl::Seconds(15);
constexpr absl::Duration kProcessNetworkChangeTimerDelay = absl::Seconds(1);
// Delay invalidating the surface state after a resume event.
// Network activities can cause system to resume for short periods before
// suspending again. This delay allows us to ignore those and only resume
// fully when the system is stable.
constexpr absl::Duration kResumeDelay = absl::Milliseconds(500);
// The duration to use join binding time when downloading public certificates.
// The default BE database query staleness is 30s. We extend this t0 40s to
// ensure that we have some overlap.
constexpr absl::Duration kJoinBindingTimeLifeTime = absl::Seconds(40);
// The maximum number of certificate downloads that can be performed during a
// discovery session.
// Assuming a 2min discovery session and 10s download interval.
@@ -251,6 +265,24 @@ sync::SyncBinding::SourceDeviceType ShareTargetTypeToSourceDeviceType(
return sync::SyncBinding::SOURCE_DEVICE_TYPE_UNKNOWN;
}
}
location::nearby::proto::sharing::SharingUseCase
IntroductionUseCaseToLoggingUseCase(
IntroductionFrame::SharingUseCase use_case) {
switch (use_case) {
case IntroductionFrame::NEARBY_SHARE:
return location::nearby::proto::sharing::SharingUseCase::
USE_CASE_NEARBY_SHARE;
case IntroductionFrame::TAP_TO_SHARE:
return location::nearby::proto::sharing::SharingUseCase::
USE_CASE_TAP_TO_SHARE;
case IntroductionFrame::FILE_SYNC:
return location::nearby::proto::sharing::SharingUseCase::
USE_CASE_FILE_SYNC;
default:
return location::nearby::proto::sharing::SharingUseCase::USE_CASE_UNKNOWN;
}
}
} // namespace
NearbySharingServiceImpl::NearbySharingServiceImpl(
@@ -318,6 +350,13 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
OnLockStateChanged(screen_status ==
nearby::api::DeviceInfo::ScreenStatus::kLocked);
});
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
kEnableSuspendResumeListener)) {
suspend_resume_listener_id_ =
device_info_.RegisterSuspendResumeListener(absl::bind_front(
&NearbySharingServiceImpl::OnSuspendResumeEvent, this));
}
account_manager_.AddObserver(this);
settings_->AddSettingsObserver(this);
@@ -365,6 +404,8 @@ void NearbySharingServiceImpl::Shutdown(
background_receive_callbacks_map_.clear();
device_info_.UnregisterScreenLockedListener(kScreenStateListenerName);
device_info_.UnregisterSuspendResumeListener(
suspend_resume_listener_id_);
settings_->RemoveSettingsObserver(this);
@@ -668,7 +709,7 @@ void NearbySharingServiceImpl::RegisterReceiveSurface(
VLOG(1) << "[Call Identity API] ForceUploadPrivateCertificates.";
certificate_manager_->ForceUploadPrivateCertificates();
}
InvalidateReceiveSurfaceState();
InvalidateAdvertisingState();
status_codes_callback(StatusCodes::kOk);
});
}
@@ -1396,6 +1437,42 @@ void NearbySharingServiceImpl::OnLockStateChanged(bool locked) {
});
}
void NearbySharingServiceImpl::OnSuspendResumeEvent(
nearby::api::DeviceInfo::SuspendResumeEvent event) {
bool suspended =
event == nearby::api::DeviceInfo::SuspendResumeEvent::kSuspend;
{
absl::MutexLock lock(suspend_mutex_);
suspended_ = suspended;
if (!suspended) {
resume_delay_timer_ = std::make_unique<ThreadTimer>(
*service_thread_, "suspend_resume_timer", kResumeDelay, [this]() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
return;
}
}
LOG(INFO) << "InvalidateSurfaceState due to system resume";
InvalidateSurfaceState();
});
}
}
if (suspended) {
RunOnNearbySharingServiceThread("on_suspend", [this]() {
LOG(INFO) << "InvalidateSurfaceState due to system suspend";
{
absl::MutexLock lock(suspend_mutex_);
if (!suspended_) {
return;
}
resume_delay_timer_.reset();
}
InvalidateSurfaceState();
});
}
}
void NearbySharingServiceImpl::AdapterPresentChanged(
sharing::api::BluetoothAdapter* adapter, bool present) {
RunOnNearbySharingServiceThread("bt_adapter_present_changed", [this, adapter,
@@ -1845,7 +1922,7 @@ bool NearbySharingServiceImpl::HasAvailableConnectionMediums() {
void NearbySharingServiceImpl::InvalidateSurfaceState() {
InvalidateSendSurfaceState();
InvalidateReceiveSurfaceState();
InvalidateAdvertisingState();
}
void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
@@ -1854,6 +1931,16 @@ void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
}
void NearbySharingServiceImpl::InvalidateScanningState() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopScanning();
VLOG(1) << __func__
<< ": Stopping discovery because the system is suspended.";
return;
}
}
// Stop scanning when screen is off.
if (is_screen_locked_) {
StopScanning();
@@ -1891,6 +1978,17 @@ void NearbySharingServiceImpl::InvalidateScanningState() {
}
void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopFastInitiationAdvertising();
VLOG(1) << __func__
<< ": Stopping fast initiation advertising because the "
"system is suspended.";
return;
}
}
// Screen is off. Do no work.
if (is_screen_locked_) {
StopFastInitiationAdvertising();
@@ -1929,13 +2027,26 @@ void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
StartFastInitiationAdvertising();
}
void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
InvalidateAdvertisingState();
}
void NearbySharingServiceImpl::InvalidateAdvertisingState() {
// Do not advertise on lock screen unless Self Share is enabled.
if (is_screen_locked_) {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopAdvertising();
VLOG(1) << __func__
<< ": Stopping advertising because the system is suspended.";
return;
}
}
bool supports_advertising_on_lock_screen =
NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
kEnableBackup) &&
sync_manager_.HasSyncBindings();
DeviceVisibility visibility = settings_->GetVisibility();
// Do not advertise on lock screen unless Self Share is enabled, or Backup is
// enabled and there are existing SyncBindings.
if (is_screen_locked_ && !supports_advertising_on_lock_screen) {
StopAdvertising();
VLOG(1) << __func__
<< ": Stopping advertising because the screen is locked.";
@@ -1969,29 +2080,51 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
// We should only advertise if the user has set the visibility to something
// other than HIDDEN or UNSPECIFIED.
if (!IsVisibleInBackground(settings_->GetVisibility())) {
if (!IsVisibleInBackground(visibility)) {
StopAdvertising();
VLOG(1) << __func__
<< ": Stopping advertising because device is visible to NO_ONE.";
return;
}
if (is_screen_locked_ && supports_advertising_on_lock_screen) {
if (visibility != DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE) {
VLOG(1) << __func__
<< ": Restarting advertising to SELF_SHARE on lock screen.";
visibility = DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE;
}
}
bool need_to_restart_advertising = false;
// This is used to set up the PairedKeyVerificationRunner correctly on
// incoming connections.
advertising_on_screen_locked_ = is_screen_locked_;
if (last_advertised_device_visibility_ !=
DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED &&
visibility != last_advertised_device_visibility_) {
StopAdvertising();
need_to_restart_advertising = true;
VLOG(1) << __func__
<< ": Restarting advertising because visibility has changed.";
}
PowerLevel power_level;
if (!foreground_receive_callbacks_map_.empty()) {
power_level = PowerLevel::kHighPower;
} else {
power_level = PowerLevel::kLowPower;
}
DataUsage data_usage = settings_->GetDataUsage();
if (advertising_power_level_ != PowerLevel::kUnknown) {
if (!need_to_restart_advertising &&
advertising_power_level_ != PowerLevel::kUnknown) {
if (power_level == advertising_power_level_) {
VLOG(1) << __func__ << ": Ignoring, already advertising with power level "
<< PowerLevelToString(advertising_power_level_)
<< " and data usage preference " << static_cast<int>(data_usage);
return;
}
StopAdvertising();
VLOG(1) << __func__ << ": Restart advertising with power level "
<< PowerLevelToString(power_level) << " and data usage preference "
@@ -1999,7 +2132,6 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
}
std::optional<std::string> device_name;
DeviceVisibility visibility = settings_->GetVisibility();
if (visibility == DeviceVisibility::DEVICE_VISIBILITY_EVERYONE) {
device_name = local_device_data_manager_->GetDeviceName();
}
@@ -2043,11 +2175,13 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
force_new_endpoint_id_ = false;
advertising_power_level_ = power_level;
last_advertised_device_visibility_ = visibility;
VLOG(1) << __func__
<< ": StartAdvertising requested over Nearby Connections: "
<< " power level: " << PowerLevelToString(power_level)
<< " screen locked: " << is_screen_locked_
<< " visibility: "
<< DeviceVisibility_Name(settings_->GetVisibility())
<< DeviceVisibility_Name(visibility)
<< " data usage: " << DataUsage_Name(data_usage)
<< " advertise device name?: "
<< (device_name.has_value() ? "yes" : "no");
@@ -2090,7 +2224,7 @@ void NearbySharingServiceImpl::StartScanning() {
scanning_start_timestamp_ = context_->GetClock()->Now();
share_foreground_send_surface_start_timestamp_ = absl::InfinitePast();
is_scanning_ = true;
InvalidateReceiveSurfaceState();
InvalidateAdvertisingState();
outgoing_targets_manager_.AllTargetsLost(
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
@@ -2333,6 +2467,15 @@ void NearbySharingServiceImpl::OnIncomingTransferUpdate(
LOG(WARNING) << __func__ << ": Unknown file paths are not empty.";
}
}
// If backup session, update last backup time in preference.
if (session.session_usage() == ShareSessionUsage::kFileSync) {
if (session.certificate()) {
sync_manager_.SetSyncConfigBackupTime(
session.certificate()->binding_id(),
metadata.status() == TransferMetadata::Status::kComplete,
context_->GetClock()->Now());
}
}
} else if (metadata.status() ==
TransferMetadata::Status::kAwaitingLocalConfirmation) {
OnTransferStarted(/*is_incoming=*/true);
@@ -2463,6 +2606,7 @@ void NearbySharingServiceImpl::OnIncomingDecryptedCertificate(
.visibility = settings_->GetVisibility(),
.last_visibility = settings_->GetLastVisibility(),
.last_visibility_time = settings_->GetLastVisibilityTimestamp(),
.screen_locked_advertising = advertising_on_screen_locked_,
},
GetCertificateManager(),
absl::bind_front(
@@ -2588,8 +2732,7 @@ void NearbySharingServiceImpl::BeginOutgoingTransfer(
bool protection_enabled =
preference_manager_.GetBoolean(PrefNames::kAdvancedProtectionEnabled,
/*default_value=*/false);
session.SetAdvancedProtectionStatus(protection_enabled,
/*advanced_protection_mismatch=*/false);
session.SetAdvancedProtectionStatus(protection_enabled);
if (session.token().empty() || !protection_enabled) {
// Auto accept if no token or if advanced protection is disabled.
OutgoingSessionAccept(session);
@@ -2624,6 +2767,20 @@ void NearbySharingServiceImpl::BeginOutgoingPairing(
});
}
std::vector<std::string> NearbySharingServiceImpl::GetCertIdsForSyncBinding() {
std::vector<std::string> cert_ids;
cert_ids.reserve(2);
if (auto id = certificate_manager_->GetPrivateCertificateId(
proto::DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE)) {
cert_ids.push_back(*id);
}
if (auto id = certificate_manager_->GetPrivateCertificateId(
proto::DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)) {
cert_ids.push_back(*id);
}
return cert_ids;
}
void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
int64_t share_target_id, absl::StatusOr<std::string> binding_status) {
RunOnNearbySharingServiceThread(
@@ -2642,11 +2799,10 @@ void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
LOG(INFO) << __func__
<< ": Sync binding rpc succeeded: id=" << binding_id;
session->StartPeerBinding(
binding_id, BindingRequest::FILESYNC,
[this, share_target_id,
binding_id](BindingResponse::Status status) {
OnPeerSyncBindingComplete(share_target_id, binding_id, status);
});
binding_id, BindingRequest::FILESYNC, GetCertIdsForSyncBinding(),
absl::bind_front(
&NearbySharingServiceImpl::OnPeerSyncBindingComplete, this,
share_target_id, binding_id));
} else {
LOG(INFO) << __func__ << ": Sync binding rpc failed.";
session->Abort(TransferMetadata::Status::kFailed);
@@ -2656,7 +2812,7 @@ void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
int64_t share_target_id, absl::string_view binding_id,
BindingResponse::Status status) {
const BindingResponse& binding_response) {
OutgoingShareSession* session =
outgoing_targets_manager_.GetOutgoingShareSession(share_target_id);
if (!session || !session->IsConnected()) {
@@ -2664,7 +2820,7 @@ void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
<< share_target_id;
return;
}
if (status != BindingResponse::SUCCESS) {
if (binding_response.status() != BindingResponse::SUCCESS) {
LOG(INFO) << __func__ << ": Sync binding response failed.";
session->Abort(TransferMetadata::Status::kFailed);
return;
@@ -2690,9 +2846,28 @@ void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
.set_binding_id(binding_id)
.set_status(TransferMetadata::Status::kComplete)
.build());
// Update binding id in peer certificates so we can identify the sync peer
// immediately without waiting for cert sync from Backend.
for (const auto& cert_id : binding_response.cert_ids()) {
certificate_manager_->AddBindingToPublicCertificate(cert_id, binding_id);
}
// Download public certificates again to update the newly added sync binding.
certificate_manager_->DownloadPublicCertificates();
if (binding_response.has_join_binding_time()) {
auto join_binding_time =
util_time::DecodeGoogleApiProto(binding_response.join_binding_time());
if (join_binding_time.ok()) {
certificate_manager_->SetJoinBindingTime(join_binding_time.value(),
kJoinBindingTimeLifeTime);
}
}
// TODO: Remove this check after BE supports cert download without join time.
// Without join time, the new download can overwrite the bindings we added
// from the binding response.
if (binding_response.has_join_binding_time()) {
// Download public certificates again to update the newly added sync
// binding.
certificate_manager_->DownloadPublicCertificates();
}
}
void NearbySharingServiceImpl::OnReceivedIntroduction(
@@ -2737,7 +2912,9 @@ void NearbySharingServiceImpl::OnReceivedIntroduction(
// Log analytics event of receiving introduction.
analytics_recorder_.NewReceiveIntroduction(
session.session_id(), session.share_target(),
/*referrer_package=*/std::nullopt, session.os_type());
/*referrer_package=*/std::nullopt, session.os_type(),
IntroductionUseCaseToLoggingUseCase(frame.use_case()),
nearby::sharing::cpp::common::GetPowerStatus());
std::optional<size_t> available_storage =
device_info_.GetAvailableDiskSpaceInBytes(save_path);
+17 -2
View File
@@ -31,11 +31,13 @@
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
#include "location/nearby/sharing/lib/sync/sync_manager.h"
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "internal/platform/clock.h"
@@ -219,6 +221,9 @@ class NearbySharingServiceImpl
// Handle the state changes of screen lock.
void OnLockStateChanged(bool locked);
void OnSuspendResumeEvent(
nearby::api::DeviceInfo::SuspendResumeEvent event);
// Handle the state changes of bluetooth adapter.
void AdapterPresentChanged(sharing::api::BluetoothAdapter* adapter,
bool present) override;
@@ -281,7 +286,6 @@ class NearbySharingServiceImpl
void InvalidateSendSurfaceState();
void InvalidateScanningState();
void InvalidateFastInitiationAdvertising();
void InvalidateReceiveSurfaceState();
void InvalidateAdvertisingState();
void StopAdvertising();
void StartScanning();
@@ -406,13 +410,14 @@ class NearbySharingServiceImpl
bool OutgoingSessionAccept(OutgoingShareSession& session);
void OnIncomingFilesMetadataUpdated(int64_t share_target_id,
TransferMetadata metadata, bool success);
std::vector<std::string> GetCertIdsForSyncBinding();
// Called when InitiateBinding rpc returns.
void OnInitiateSyncBindingResponse(
int64_t share_target_id, absl::StatusOr<std::string> binding_status);
// Called when Bindings response frame is received from the peer.
void OnPeerSyncBindingComplete(
int64_t share_target_id, absl::string_view binding_id,
service::proto::BindingResponse::Status status);
const service::proto::BindingResponse& binding_response);
// Notify all registered send surfaces of share target state changes.
void NotifyShareTargetDiscovered(const ShareTarget& share_target);
@@ -546,6 +551,16 @@ class NearbySharingServiceImpl
bool force_new_endpoint_id_ = false;
OutgoingTargetsManager outgoing_targets_manager_;
nearby::sharing::SyncManager sync_manager_;
// Visibility used for the last advertisement.
proto::DeviceVisibility last_advertised_device_visibility_ =
proto::DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED;
bool advertising_on_screen_locked_ = false;
int64_t suspend_resume_listener_id_ = 0;
absl::Mutex suspend_mutex_;
bool suspended_ ABSL_GUARDED_BY(suspend_mutex_) = false;
std::unique_ptr<ThreadTimer> resume_delay_timer_
ABSL_GUARDED_BY(suspend_mutex_);
};
} // namespace nearby::sharing
+42 -7
View File
@@ -30,6 +30,7 @@
#include <utility>
#include <vector>
#include "google/protobuf/timestamp.pb.h"
#include "location/nearby/analytics/cpp/logging/mock_event_logger.h"
#include "location/nearby/sharing/lib/account/fake_account_manager.h"
#include "location/nearby/sharing/lib/account/mock_account_observer.h"
@@ -4638,6 +4639,34 @@ TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringAdvertising) {
EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown());
}
TEST_F(NearbySharingServiceImplTest,
ScreenLocksDuringAdvertisingWithBackupAndSyncBindings) {
// Enable Backup flag.
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
// Add SyncBindings.
nearby::sharing::sync::SyncBindingPrefs sync_binding_prefs;
auto* binding = sync_binding_prefs.add_sync_bindings();
binding->set_binding_id("test_binding_id");
service_->GetSettings()->SetSyncBindingPrefs(sync_binding_prefs);
SetLanConnected(true);
SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS);
MockTransferUpdateCallback callback;
NearbySharingService::StatusCodes result = RegisterReceiveSurface(
&callback, NearbySharingService::ReceiveSurfaceState::kForeground);
EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk);
ScopedReceiveSurface r(service_.get(), &callback);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown());
// Screen locks, but we should STILL be advertising.
SetScreenLocked(true);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown());
}
TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringDiscovery) {
SetLanConnected(true);
MockTransferUpdateCallback transfer_callback;
@@ -5151,6 +5180,7 @@ TEST_F(NearbySharingServiceImplTest,
EXPECT_EQ(frame->v1().bindings().binding_request().binding_id(), kBindingId);
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
service::proto::BindingRequest::FILESYNC);
EXPECT_EQ(frame->v1().bindings().binding_request().cert_ids_size(), 2);
// BindingResponse frame timeout.
FastForward(absl::Seconds(60));
@@ -5201,15 +5231,18 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) {
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
service::proto::BindingRequest::FILESYNC);
preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads");
FilePath custom_save_path = Files::GetTemporaryDirectory();
preference_manager_.SetString(PrefNames::kCustomSavePath,
custom_save_path.ToString());
Frame binding_response_frame;
binding_response_frame.set_version(Frame::V1);
binding_response_frame.mutable_v1()->set_type(
service::proto::V1Frame::BINDINGS);
binding_response_frame.mutable_v1()
auto* binding_response = binding_response_frame.mutable_v1()
->mutable_bindings()
->mutable_binding_response()
->set_status(service::proto::BindingResponse::SUCCESS);
->mutable_binding_response();
binding_response->set_status(service::proto::BindingResponse::SUCCESS);
binding_response->mutable_join_binding_time()->set_seconds(1234567890);
std::vector<uint8_t> result_bytes(binding_response_frame.ByteSizeLong());
binding_response_frame.SerializeToArray(result_bytes.data(),
result_bytes.size());
@@ -5230,7 +5263,7 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) {
expected_binding.set_binding_id(kBindingId);
expected_binding.set_source_name(kDeviceName);
expected_binding.set_destination_directory(
FilePath("Downloads").append(FilePath(kDeviceName)).ToString());
FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString());
expected_binding.set_source_device_type(
sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE);
EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding));
@@ -5305,7 +5338,9 @@ TEST_F(NearbySharingServiceImplTest,
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
service::proto::BindingRequest::FILESYNC);
preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads");
FilePath custom_save_path = Files::GetTemporaryDirectory();
preference_manager_.SetString(PrefNames::kCustomSavePath,
custom_save_path.ToString());
Frame binding_response_frame;
binding_response_frame.set_version(Frame::V1);
binding_response_frame.mutable_v1()->set_type(
@@ -5332,7 +5367,7 @@ TEST_F(NearbySharingServiceImplTest,
expected_binding.set_binding_id(kBindingId);
expected_binding.set_source_name(kDeviceName);
expected_binding.set_destination_directory(
FilePath("Downloads").append(FilePath(kDeviceName)).ToString());
FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString());
expected_binding.set_source_device_type(
sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE);
EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding));
+11 -1
View File
@@ -26,6 +26,8 @@
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.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/implementation/device_info.h"
#include "internal/platform/task_runner.h"
@@ -184,8 +186,12 @@ void NearbyShareSettings::RestoreFallbackVisibility() {
}
std::string NearbyShareSettings::GetCustomSavePath() const {
return preference_manager_.GetString(
std::string custom_save_path = preference_manager_.GetString(
PrefNames::kCustomSavePath, device_info_.GetDownloadPath().ToString());
if (Files::IsAbsolutePath(FilePath(custom_save_path))) {
return custom_save_path;
}
return device_info_.GetDownloadPath().ToString();
}
SyncBindingPrefs NearbyShareSettings::GetSyncBindingPrefs() const {
@@ -347,6 +353,10 @@ void NearbyShareSettings::SetFallbackVisibility(DeviceVisibility visibility) {
void NearbyShareSettings::SetCustomSavePathAsync(
absl::string_view save_path, const std::function<void()>& callback) {
if (!Files::IsAbsolutePath(FilePath(save_path))) {
callback();
return;
}
absl::MutexLock lock(mutex_);
preference_manager_.SetString(PrefNames::kCustomSavePath, save_path);
callback();
+17 -13
View File
@@ -23,9 +23,11 @@
#include <utility>
#include <vector>
#include "location/nearby/cpp/sharing/clients/cpp/common/nearby_sharing_common.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/platform/clock.h"
@@ -372,8 +374,7 @@ void OutgoingShareSession::SendPayloads(
analytics_recorder().NewSendAttachmentsStart(
session_id(), attachment_container(),
/*transfer_position=*/1,
/*concurrent_connections=*/1, advanced_protection_enabled_,
advanced_protection_mismatch_);
/*concurrent_connections=*/1, advanced_protection_enabled_);
VLOG(1) << "The connection was accepted. Payloads are now being sent.";
InitializePayloadTracker(std::move(payload_transder_update_callback));
SendNextPayload();
@@ -423,10 +424,11 @@ bool OutgoingShareSession::SendIntroduction(
}
WriteFrame(frame);
// Log analytics event of sending introduction.
analytics_recorder().NewSendIntroduction(session_id(), share_target(),
/*transfer_position=*/1,
/*concurrent_connections=*/1,
os_type());
analytics_recorder().NewSendIntroduction(
session_id(), share_target(),
/*transfer_position=*/1,
/*concurrent_connections=*/1, os_type(),
nearby::sharing::cpp::common::GetPowerStatus());
VLOG(1) << "Successfully wrote the introduction frame";
ready_for_accept_ = true;
mutual_acceptance_timeout_ = std::make_unique<ThreadTimer>(
@@ -646,7 +648,8 @@ OutgoingShareSession::ProcessPayloadTransferUpdates() {
void OutgoingShareSession::StartPeerBinding(
std::string binding_id, BindingRequest::Type binding_type,
absl::AnyInvocable<void(BindingResponse::Status)> callback) {
absl::Span<const std::string> cert_ids,
absl::AnyInvocable<void(const BindingResponse&)> callback) {
Frame frame;
frame.set_version(Frame::V1);
V1Frame* v1_frame = frame.mutable_v1();
@@ -655,6 +658,7 @@ void OutgoingShareSession::StartPeerBinding(
v1_frame->mutable_bindings()->mutable_binding_request();
binding_request->set_binding_id(binding_id);
binding_request->set_type(binding_type);
binding_request->mutable_cert_ids()->Add(cert_ids.begin(), cert_ids.end());
WriteFrame(frame);
LOG(INFO) << "Waiting for bindings response frame from " << share_target().id;
UpdateTransferMetadata(
@@ -667,19 +671,19 @@ void OutgoingShareSession::StartPeerBinding(
nearby::sharing::service::proto::V1Frame::BINDINGS,
[callback = std::move(callback)](
bool is_timeout, std::optional<V1Frame> frame) mutable {
BindingResponse failure_response;
failure_response.set_status(BindingResponse::FAILURE);
if (!frame.has_value()) {
std::move(callback)(BindingResponse::FAILURE);
std::move(callback)(failure_response);
return;
}
if (!frame->has_bindings() ||
!frame->bindings().has_binding_response() ||
frame->bindings().binding_response().status() !=
BindingResponse::SUCCESS) {
std::move(callback)(BindingResponse::FAILURE);
!frame->bindings().has_binding_response()) {
std::move(callback)(failure_response);
return;
}
// Peer binding flow completed successfully.
std::move(callback)(BindingResponse::SUCCESS);
std::move(callback)(frame->bindings().binding_response());
},
kReadResponseFrameTimeout);
}
+6 -5
View File
@@ -26,6 +26,7 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "internal/platform/clock.h"
#include "internal/platform/task_runner.h"
#include "sharing/analytics/analytics_recorder.h"
@@ -141,10 +142,8 @@ class OutgoingShareSession : public ShareSession {
std::optional<TransferMetadata> ProcessPayloadTransferUpdates();
void SetAdvancedProtectionStatus(bool advanced_protection_enabled,
bool advanced_protection_mismatch) {
void SetAdvancedProtectionStatus(bool advanced_protection_enabled) {
advanced_protection_enabled_ = advanced_protection_enabled;
advanced_protection_mismatch_ = advanced_protection_mismatch;
}
// Returns true if the session is connected or in the process of connecting.
@@ -166,13 +165,16 @@ class OutgoingShareSession : public ShareSession {
// Initiates the peer binding message exchange with the remote device.
// `binding_id` is the result of a successful call to InitiateBinding rpc.
// `cert_ids` are the public certificate ids that can be used to identify this
// device.
// `callback` is called when either a BindingResponse frame is received or a
// timeout occurs.
void StartPeerBinding(
std::string binding_id,
nearby::sharing::service::proto::BindingRequest::Type binding_type,
absl::Span<const std::string> cert_ids,
absl::AnyInvocable<
void(nearby::sharing::service::proto::BindingResponse::Status)>
void(const nearby::sharing::service::proto::BindingResponse&)>
callback);
protected:
@@ -210,7 +212,6 @@ class OutgoingShareSession : public ShareSession {
// Timeout waiting for remote disconnect in order to complete transfer.
std::unique_ptr<ThreadTimer> disconnection_timeout_;
bool advanced_protection_enabled_ = false;
bool advanced_protection_mismatch_ = false;
bool is_connecting_ = false;
// Session can be for transfer or pairing.
bool is_transfer_session_ = false;
+31 -32
View File
@@ -74,6 +74,7 @@ using ::nearby::sharing::service::proto::V1Frame;
using ::nearby::sharing::service::proto::WifiCredentials;
using ::testing::_;
using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::protobuf_matchers::EqualsProto;
using ::testing::InSequence;
@@ -676,11 +677,7 @@ TEST_F(OutgoingShareSessionTest, SendPayloads) {
Log(Matcher<const SharingLog&>(AllOf(
(HasCategory(EventCategory::SENDING_EVENT),
HasEventType(EventType::SEND_ATTACHMENTS_START),
ProtoField<"send_attachments_start", "session_id">(1234),
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
false),
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
false))))));
ProtoField<"send_attachments_start", "session_id">(1234))))));
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
@@ -717,15 +714,12 @@ TEST_F(OutgoingShareSessionTest, SendPayloadsSetsAdvancedProtectionFlags) {
HasEventType(EventType::SEND_ATTACHMENTS_START),
ProtoField<"send_attachments_start", "session_id">(1234),
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
true),
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
true))))));
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
session_.SetAdvancedProtectionStatus(/*advanced_protection_enabled=*/true,
/*advanced_protection_mismatch=*/true);
session_.SetAdvancedProtectionStatus(/*advanced_protection_enabled=*/true);
session_.SendPayloads([](bool is_timeout, std::optional<V1Frame> frame) {},
payload_transder_update_callback.AsStdFunction());
@@ -759,8 +753,6 @@ TEST_F(OutgoingShareSessionTest, SendNextPayload) {
HasEventType(EventType::SEND_ATTACHMENTS_START),
ProtoField<"send_attachments_start", "session_id">(1234),
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
false),
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
false))))));
NearbyConnectionImpl connection(device_info_);
ConnectionSuccess(&connection);
@@ -937,6 +929,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
binding_request {
binding_id: "test_binding_id"
type: FILESYNC
cert_ids: "cert_id_1"
cert_ids: "cert_id_2"
}
}
}
@@ -954,12 +948,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
HasUsage(ShareSessionUsage::kPairing))));
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
[&binding_response_status](
BindingResponse::Status status) {
binding_response_status = status;
});
BindingResponse binding_response;
session_.StartPeerBinding(
"test_binding_id", BindingRequest::FILESYNC, {"cert_id_1", "cert_id_2"},
[&binding_response](const BindingResponse& response) {
binding_response = response;
});
Frame frame;
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
@@ -976,6 +970,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
bindings {
binding_response {
status: SUCCESS
cert_ids: "cert_id_3"
cert_ids: "cert_id_4"
}
}
}
@@ -987,7 +983,9 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
IsTrue());
connection.WriteMessage(std::move(data));
EXPECT_THAT(binding_response_status, Eq(BindingResponse::SUCCESS));
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::SUCCESS));
EXPECT_THAT(binding_response.cert_ids(),
ElementsAre("cert_id_3", "cert_id_4"));
}
TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
@@ -1022,12 +1020,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
HasUsage(ShareSessionUsage::kPairing))));
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
[&binding_response_status](
BindingResponse::Status status) {
binding_response_status = status;
});
BindingResponse binding_response;
session_.StartPeerBinding(
"test_binding_id", BindingRequest::FILESYNC, {},
[&binding_response](const BindingResponse& response) {
binding_response = response;
});
Frame frame;
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
@@ -1038,7 +1036,7 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
fake_clock_.FastForward(absl::Seconds(60));
fake_task_runner_.SyncWithTimeout(absl::Milliseconds(100));
EXPECT_THAT(binding_response_status, Eq(BindingResponse::FAILURE));
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::FAILURE));
}
TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
@@ -1073,12 +1071,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
HasUsage(ShareSessionUsage::kPairing))));
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
[&binding_response_status](
BindingResponse::Status status) {
binding_response_status = status;
});
BindingResponse binding_response;
session_.StartPeerBinding(
"test_binding_id", BindingRequest::FILESYNC, {},
[&binding_response](const BindingResponse& response) {
binding_response = response;
});
Frame frame;
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
@@ -1106,7 +1104,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
IsTrue());
connection.WriteMessage(std::move(data));
EXPECT_THAT(binding_response_status, Eq(BindingResponse::FAILURE));
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::FAILURE));
EXPECT_THAT(binding_response.cert_ids(), IsEmpty());
}
} // namespace
+37 -24
View File
@@ -140,18 +140,8 @@ void PairedKeyVerificationRunner::OnReadPairedKeyEncryptionFrame(
OSType::UNKNOWN_OS_TYPE);
return;
}
PairedKeyVerificationResult auth_token_hash_result =
VerifyAuthTokenHashWithPrivateCertificate(visibility_history_.visibility,
*frame);
if (auth_token_hash_result != PairedKeyVerificationResult::kSuccess) {
if (IsVisibilityRecentlyUpdated()) {
auth_token_hash_result = VerifyAuthTokenHashWithPrivateCertificate(
visibility_history_.last_visibility, *frame);
}
}
VerifyAuthTokenHashWithPrivateCertificates(*frame);
if (auth_token_hash_result == PairedKeyVerificationResult::kUnable) {
if (share_target_is_incoming_ &&
visibility_history_.visibility !=
@@ -255,9 +245,18 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
share_target_is_incoming_ ? kNearbyShareReceiverVerificationPrefix
: kNearbyShareSenderVerificationPrefix,
raw_token_);
DeviceVisibility primary_visibility;
DeviceVisibility secondary_visibility;
if (visibility_history_.screen_locked_advertising) {
primary_visibility = DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE;
secondary_visibility = visibility_history_.visibility;
} else {
primary_visibility = visibility_history_.visibility;
secondary_visibility = visibility_history_.last_visibility;
}
std::optional<std::vector<uint8_t>> signature =
certificate_manager_.SignWithPrivateCertificate(
visibility_history_.visibility, padded_token);
certificate_manager_.SignWithPrivateCertificate(primary_visibility,
padded_token);
if (!signature.has_value() || signature->empty()) {
signature = GenerateRandomBytes(kNearbyShareNumBytesRandomSignature);
}
@@ -282,8 +281,8 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
LOG(INFO)
<< "Attempts to sign authentication token with a previous private key.";
std::optional<std::vector<uint8_t>> optional_signature =
certificate_manager_.SignWithPrivateCertificate(
visibility_history_.last_visibility, padded_token);
certificate_manager_.SignWithPrivateCertificate(secondary_visibility,
padded_token);
if (optional_signature.has_value()) {
encryption_frame->set_optional_signed_data(optional_signature->data(),
@@ -297,22 +296,36 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
}
PairedKeyVerificationRunner::PairedKeyVerificationResult
PairedKeyVerificationRunner::VerifyAuthTokenHashWithPrivateCertificate(
DeviceVisibility visibility,
PairedKeyVerificationRunner::VerifyAuthTokenHashWithPrivateCertificates(
const nearby::sharing::service::proto::V1Frame& frame) {
std::optional<std::vector<uint8_t>> hash =
certificate_manager_.HashAuthenticationTokenWithPrivateCertificate(
visibility, raw_token_);
const std::string& frame_hash =
frame.paired_key_encryption().secret_id_hash();
std::vector<uint8_t> frame_hash_data{frame_hash.begin(), frame_hash.end()};
if (hash.has_value() && *hash == frame_hash_data) {
VLOG(1) << __func__ << ": Successfully verified remote public certificate.";
return PairedKeyVerificationResult::kSuccess;
std::vector<DeviceVisibility> visibilities_to_check;
// At most 3 visibilities to check.
visibilities_to_check.reserve(3);
// If we are advertising under lock screen then verify against self share
// private certificate first.
if (visibility_history_.screen_locked_advertising) {
visibilities_to_check.push_back(
DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE);
}
visibilities_to_check.push_back(visibility_history_.visibility);
if (IsVisibilityRecentlyUpdated()) {
visibilities_to_check.push_back(visibility_history_.last_visibility);
}
for (const auto& visibility : visibilities_to_check) {
std::optional<std::vector<uint8_t>> hash =
certificate_manager_.HashAuthenticationTokenWithPrivateCertificate(
visibility, raw_token_);
if (hash.has_value() && *hash == frame_hash_data) {
VLOG(1) << __func__
<< ": Successfully verified remote public certificate.";
return PairedKeyVerificationResult::kSuccess;
}
}
VLOG(1) << __func__ << ": Unable to verify remote public certificate.";
return PairedKeyVerificationResult::kUnable;
}
+6 -4
View File
@@ -51,6 +51,8 @@ class PairedKeyVerificationRunner
proto::DeviceVisibility visibility;
proto::DeviceVisibility last_visibility;
absl::Time last_visibility_time;
// Set to true if device is advertising under lock screen.
bool screen_locked_advertising = false;
};
PairedKeyVerificationRunner(
@@ -85,10 +87,10 @@ class PairedKeyVerificationRunner
void OnReadPairedKeyResultFrame(
std::optional<nearby::sharing::service::proto::V1Frame> frame);
void SendPairedKeyResultFrame(PairedKeyVerificationResult result);
// Verifies auth token hash in frame using private certificate for visibility.
// Returns either kSuccess or kUnable. This function never returns kFail.
PairedKeyVerificationResult VerifyAuthTokenHashWithPrivateCertificate(
proto::DeviceVisibility visibility,
// Verifies auth token hash in frame using private certificates in
// `visibility_history_`. Returns either kSuccess or kUnable. This function
// never returns kFail.
PairedKeyVerificationResult VerifyAuthTokenHashWithPrivateCertificates(
const nearby::sharing::service::proto::V1Frame& frame);
PairedKeyVerificationResult VerifyPairedKeyEncryptionFrame(
const nearby::sharing::service::proto::V1Frame& frame);
+15 -7
View File
@@ -126,9 +126,13 @@ GenerateVisibilityHistory() {
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE,
};
std::list<PairedKeyVerificationRunner::VisibilityHistory> result;
for (DeviceVisibility visibility : kValidVisibilities) {
for (DeviceVisibility last_visibility : kValidVisibilities) {
result.push_back({visibility, last_visibility, absl::UnixEpoch()});
for (bool screen_locked_advertising : {true, false}) {
for (DeviceVisibility visibility : kValidVisibilities) {
for (DeviceVisibility last_visibility : kValidVisibilities) {
result.push_back(
{visibility, last_visibility, absl::UnixEpoch(),
screen_locked_advertising});
}
}
}
return result;
@@ -476,10 +480,12 @@ TEST_P(ParameterisedPairedKeyVerificationRunnerTest,
std::get<2>(GetParam());
PairedKeyVerificationRunner::PairedKeyVerificationResult result =
params.result;
// If our visibility has no certificates, then downgrade expected result to
// kUnable if it is not expected to fail.
// If our visibility has no certificates (i.e. EVERYONE and not under lock
// screen), then downgrade expected result to kUnable if it is not expected to
// fail.
if ((visibility_history.visibility ==
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE) &&
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE &&
!visibility_history.screen_locked_advertising) &&
!(visibility_history.last_visibility !=
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE &&
(params.encryption_frame_type ==
@@ -511,7 +517,9 @@ TEST_P(ParameterisedPairedKeyVerificationRunnerTest,
<< ", expected_result=" << (int)expected_result
<< ", result_frame=" << (int)result_frame.status()
<< ", visibility=" << (int)visibility_history.visibility
<< ", last_visibility=" << (int)visibility_history.last_visibility;
<< ", last_visibility=" << (int)visibility_history.last_visibility
<< ", screen_locked_advertising="
<< visibility_history.screen_locked_advertising;
SetUpPairedKeyEncryptionFrame(params.encryption_frame_type);
bool encryption_frame_timeout =
+4 -1
View File
@@ -42,7 +42,10 @@ proto_library(
name = "wire_format_proto",
srcs = ["wire_format.proto"],
visibility = ["//visibility:public"],
deps = ["//proto:sharing_enums_proto"],
deps = [
"//google/protobuf:timestamp",
"//proto:sharing_enums_proto",
],
)
cc_proto_library(
+14
View File
@@ -16,6 +16,8 @@ syntax = "proto2";
package nearby.sharing.service.proto;
import "google/protobuf/timestamp.proto";
// import "storage/datapol/annotations/proto/semantic_annotations.proto";
import "proto/sharing_enums.proto";
@@ -233,6 +235,7 @@ message IntroductionFrame {
repeated StreamMetadata stream_metadata = 7;
optional SharingUseCase use_case = 8;
repeated int64 preview_payload_ids = 9;
optional string transfer_id = 10;
}
// A progress update packet sent by the sending side. Contains transfer progress
@@ -265,6 +268,13 @@ message BindingRequest {
}
optional string binding_id = 1;
optional Type type = 2;
// A list of public cert ids that can be used to identify the sender.
// If binding is successful, the receiver can add the binding ids to these
// public certs to ensure that it can immediately identify the sender without
// having to download public certs from the BE.
// The sender does not need to provide all its future public certs, just the
// current ones will be sufficient.
repeated bytes cert_ids = 3;
}
message BindingResponse {
@@ -274,6 +284,10 @@ message BindingResponse {
FAILURE = 2; // TODO: b/485307320 - Add more specific error codes.
}
optional Status status = 1;
optional google.protobuf.Timestamp join_binding_time = 2;
// A list of public cert ids that can be used to identify the receiver.
// See the comment of cert_ids in BindingRequest for more details.
repeated bytes cert_ids = 3;
}
// A response packet sent by the receiving side. Accepts or rejects the list of