Persist advertising endpoint ID.

PiperOrigin-RevId: 820267327
This commit is contained in:
Guogang Li
2025-10-16 09:25:06 -07:00
committed by Copybara-Service
parent 57dea973e0
commit 4c37f90965
10 changed files with 174 additions and 4 deletions
+9
View File
@@ -844,3 +844,12 @@ void NcSetPhenotypeFlagReader(READER_CONTEXT context,
context, phenotype_flag_reader);
nearby::NearbyFlags::GetInstance().SetFlagReader(*kNearbyFlags);
}
void NcSaveStates(NC_INSTANCE instance) {
NcContext* nc_context = GetContext(instance);
if (nc_context == nullptr) {
return;
}
nc_context->core->SaveStates();
}
+4
View File
@@ -196,6 +196,10 @@ NC_API void NcSetCustomSavePath(NC_INSTANCE instance, const NC_DATA* save_path,
NC_API void NcSetPhenotypeFlagReader(
READER_CONTEXT context, NC_PHENOTYPE_FLAG_READER phenotype_flag_reader);
// Saves the states of Nearby Connections to preferences. This is used to
// restore the states when restart the Nearby Connections.
NC_API void NcSaveStates(NC_INSTANCE instance);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+2
View File
@@ -207,6 +207,8 @@ void Core::SetCustomSavePath(absl::string_view path, ResultCallback callback) {
router_->SetCustomSavePath(&client_, path, std::move(callback));
}
void Core::SaveStates() { client_.SaveClientInfoToPreferences(); }
std::string Core::Dump() { return client_.Dump(); }
// V3
+4
View File
@@ -258,6 +258,10 @@ class Core {
// Gets the local endpoint generated by Nearby Connections.
std::string GetLocalEndpointId() { return client_.GetLocalEndpointId(); }
// Saves the states of Nearby Connections to preferences. This is used to
// restore the states when restart the Nearby Connections.
void SaveStates();
std::string Dump();
//******************************* V3 *******************************
+1
View File
@@ -166,6 +166,7 @@ cc_library(
"//connections/v3:v3_types",
"//internal/analytics:event_logger",
"//internal/base:file_path",
"//internal/base:files",
"//internal/base:masker",
"//internal/flags:nearby_flags",
"//internal/interop:authentication_status",
+77 -3
View File
@@ -31,6 +31,7 @@
#include "absl/random/random.h"
#include "absl/strings/escaping.h"
#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"
@@ -53,6 +54,7 @@
#include "connections/v3/listeners.h"
#include "internal/analytics/event_logger.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/flags/nearby_flags.h"
#include "internal/interop/device.h"
#include "internal/platform/byte_array.h"
@@ -63,6 +65,7 @@
#include "internal/platform/error_code_recorder.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/system_clock.h"
#include "internal/platform/logging.h"
#include "internal/platform/mac_address.h"
#include "internal/platform/mutex_lock.h"
@@ -85,6 +88,13 @@ constexpr char kEndpointIdChars[] = {
constexpr absl::string_view kPreferencesFilePath = "Google/Nearby/Connections";
constexpr absl::string_view kAdvertisingEndpointId =
"nc.advertising.endpoint_id";
constexpr absl::string_view kAdvertisingTimestamp = "nc.advertising.timestamp";
constexpr absl::Duration kAdvertisingKeepAliveDuration = absl::Seconds(30);
bool IsFeatureUseStableEndpointIdEnabled() {
return NearbyFlags::GetInstance().GetBoolFlag(
connections::config_package_nearby::nearby_connections_feature::
@@ -125,6 +135,9 @@ ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger)
// Generate a 7 bits dedup value.
absl::BitGen bitgen;
dct_dedup_ = absl::Uniform(bitgen, 0, 1 << 7);
// Load advertising info from preferences.
LoadClientInfoFromPreferences();
}
ClientProxy::~ClientProxy() { Reset(); }
@@ -1360,10 +1373,16 @@ void ClientProxy::InitializePreferencesManager() {
LOG(INFO) << "ClientProxy [InitializePreferencesManager]: client="
<< GetClientId();
auto device_info_ = std::make_unique<nearby::DeviceInfoImpl>();
FilePath preferences_path =
device_info_->GetAppDataPath().append(FilePath(kPreferencesFilePath));
if (!Files::FileExists(preferences_path)) {
Files::CreateDirectories(preferences_path);
}
preferences_manager_ = api::ImplementationPlatform::CreatePreferencesManager(
device_info_->GetAppDataPath()
.append(FilePath(kPreferencesFilePath))
.ToString());
preferences_path.ToString());
if (preferences_manager_ == nullptr) {
LOG(ERROR) << "ClientProxy [Failed to initialize preferences manager]: "
@@ -1372,6 +1391,61 @@ void ClientProxy::InitializePreferencesManager() {
}
}
void ClientProxy::SaveClientInfoToPreferences() {
MutexLock lock(&mutex_);
if (preferences_manager_ == nullptr) {
return;
}
if (advertising_info_.IsEmpty()) {
preferences_manager_->Remove(kAdvertisingEndpointId);
preferences_manager_->Remove(kAdvertisingTimestamp);
return;
}
preferences_manager_->SetString(kAdvertisingEndpointId, local_endpoint_id_);
preferences_manager_->SetTime(kAdvertisingTimestamp,
SystemClock::ElapsedRealtime());
LOG(INFO) << "ClientProxy [SaveClientInfoToPreferences]: client="
<< GetClientId() << "; local_endpoint_id_=" << local_endpoint_id_;
}
void ClientProxy::LoadClientInfoFromPreferences() {
MutexLock lock(&mutex_);
if (preferences_manager_ == nullptr) {
return;
}
absl::Time last_advertising_time = preferences_manager_->GetTime(
kAdvertisingTimestamp, absl::InfinitePast());
if (SystemClock::ElapsedRealtime() - last_advertising_time <
kAdvertisingKeepAliveDuration) {
std::string endpoint_id =
preferences_manager_->GetString(kAdvertisingEndpointId, "");
if (!endpoint_id.empty() && endpoint_id.length() == kEndpointIdLength) {
bool is_valid_endpoint_id = true;
for (const auto& c : endpoint_id) {
if (!((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))) {
is_valid_endpoint_id = false;
break;
}
}
if (is_valid_endpoint_id) {
local_endpoint_id_ = endpoint_id;
cached_endpoint_id_ = local_endpoint_id_;
LOG(INFO) << "ClientProxy [LoadClientInfoFromPreferences]: client="
<< GetClientId()
<< "; local_endpoint_id_=" << local_endpoint_id_;
}
}
}
preferences_manager_->Remove(kAdvertisingEndpointId);
preferences_manager_->Remove(kAdvertisingTimestamp);
}
std::string ClientProxy::ToString(PayloadProgressInfo::Status status) const {
switch (status) {
case PayloadProgressInfo::Status::kSuccess:
@@ -372,6 +372,9 @@ class ClientProxy final {
// Forces client to regenerate a new local endpoint id.
void ClearCachedLocalEndpointId();
// Saves the client information to preferences.
void SaveClientInfoToPreferences();
private:
struct Connection {
// Status: may be either:
@@ -460,6 +463,7 @@ class ClientProxy final {
std::optional<std::string> GetEndpointIdForDct() const;
void InitializePreferencesManager();
void LoadClientInfoFromPreferences();
// The device name used for DCT advertising.
std::string dct_device_name_;
@@ -162,7 +162,8 @@ class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags::Flags> {
void SetUp() override {
EnvironmentConfig config{/*webrtc_enabled=*/false,
/*use_simulated_clock=*/true};
/*use_simulated_clock=*/true,
/*use_temporary_directory_for_app_path=*/true};
env_.Start(config);
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
client2_ = std::make_unique<ClientProxy>(&event_logger2_);
@@ -1621,6 +1622,66 @@ TEST_F(ClientProxyTest, TestRemoteMultiplexSocketBitmask) {
false);
}
TEST_F(ClientProxyTest, SaveClientInfoFromPreferences) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kUseStableEndpointId,
true);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
true);
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
std::string endpoint_id = advertising_endpoint.id;
client1_->SaveClientInfoToPreferences();
// Destroy the client and create a new one.
client1_.reset();
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
// The new client should load the same endpoint ID.
EXPECT_EQ(client1()->GetLocalEndpointId(), endpoint_id);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kUseStableEndpointId,
false);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
false);
}
TEST_F(ClientProxyTest, NotLoadClientInfoFromPreferencesOnExpired) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kUseStableEndpointId,
true);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
true);
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
std::string endpoint_id = advertising_endpoint.id;
client1_->SaveClientInfoToPreferences();
// Destroy the client and create a new one.
client1_.reset();
FastForward(absl::Hours(25));
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
// The new client should load the same endpoint ID.
EXPECT_NE(client1()->GetLocalEndpointId(), endpoint_id);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kUseStableEndpointId,
false);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
false);
}
} // namespace
} // namespace connections
} // namespace nearby
@@ -26,6 +26,7 @@
#include "internal/base/files.h"
#include "internal/platform/implementation/device_info.h"
#include "internal/platform/implementation/g3/linux_path_util.h"
#include "internal/platform/medium_environment.h"
namespace nearby {
namespace g3 {
@@ -49,6 +50,12 @@ class DeviceInfo : public api::DeviceInfo {
}
std::optional<FilePath> GetLocalAppDataPath() const override {
if (MediumEnvironment::Instance()
.GetEnvironmentConfig()
.use_temporary_directory_for_app_path) {
return Files::GetTemporaryDirectory();
}
return GetAppDataPath();
}
+4
View File
@@ -63,6 +63,10 @@ struct EnvironmentConfig {
// The simulated clock is automatically picked up by SystemClock, Timer and
// ScheduledExecutor implementations.
bool use_simulated_clock = false;
// If true, the app data path will be a temporary directory, instead of the
// actual app data path, so that we can test the preferences manager under G3.
bool use_temporary_directory_for_app_path = false;
};
// MediumEnvironment is a simulated environment which allows multiple instances