Handle App lifecycle in Nearby Connections.

PiperOrigin-RevId: 822749438
This commit is contained in:
Guogang Li
2025-10-22 14:53:33 -07:00
committed by Copybara-Service
parent bd21843464
commit e37b501e37
16 changed files with 342 additions and 22 deletions
-9
View File
@@ -840,12 +840,3 @@ 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,10 +196,6 @@ 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,8 +207,6 @@ 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,10 +258,6 @@ 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 *******************************
@@ -64,6 +64,7 @@
#include "internal/platform/error_code_params.h"
#include "internal/platform/error_code_recorder.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/system_clock.h"
#include "internal/platform/logging.h"
@@ -138,6 +139,19 @@ ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger)
// Load advertising info from preferences.
LoadClientInfoFromPreferences();
if (preferences_manager_ != nullptr) {
app_lifecycle_monitor_ =
api::ImplementationPlatform::CreateAppLifecycleMonitor(
[this](api::AppLifecycleMonitor::AppLifecycleState state) {
if (state ==
api::AppLifecycleMonitor::AppLifecycleState::kInactive ||
state == api::AppLifecycleMonitor::AppLifecycleState::
kBackground) {
SaveClientInfoToPreferences();
}
});
}
}
ClientProxy::~ClientProxy() { Reset(); }
@@ -45,6 +45,7 @@
#include "internal/platform/cancelable_alarm.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/error_code_recorder.h"
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#include "internal/platform/implementation/preferences_manager.h"
#include "internal/platform/mac_address.h"
#include "internal/platform/mutex.h"
@@ -541,6 +542,9 @@ class ClientProxy final {
std::unique_ptr<CancellationFlag> default_cancellation_flag_ =
std::make_unique<CancellationFlag>(true);
// An app lifecycle monitor for monitoring the app lifecycle state.
std::unique_ptr<api::AppLifecycleMonitor> app_lifecycle_monitor_;
// A preferences manager for storing client-specific preferences.
std::unique_ptr<nearby::api::PreferencesManager> preferences_manager_;
+1
View File
@@ -149,6 +149,7 @@ cc_library(
cc_library(
name = "comm",
hdrs = [
"app_lifecycle_monitor.h",
"awdl.h",
"ble.h",
"bluetooth_adapter.h",
@@ -0,0 +1,57 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APP_LIFECYCLE_MONITOR_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APP_LIFECYCLE_MONITOR_H_
#include <functional>
#include <utility>
namespace nearby {
namespace api {
class AppLifecycleMonitor {
public:
// The state of the app lifecycle. The state transition is kBackground ->
// kInactive -> kActive. Foreground is an umbrella term that describes the app
// when it is either Inactive or Active.
enum class AppLifecycleState {
// The app is active when it starts to receive events.
kActive,
// The app is inactive but is still not in background.
kInactive,
// The app is background.
kBackground,
};
// Registers callbacks for connection changes. The callbacks will be called
// when device is connected to a LAN network or when the device is connected
// to internet.
explicit AppLifecycleMonitor(
std::function<void(AppLifecycleState)> state_updated_callback)
: state_updated_callback_(std::move(state_updated_callback)) {}
virtual ~AppLifecycleMonitor() = default;
protected:
// The callback to be called when the app lifecycle state is updated. In
// order to make it possible to be called from different methods, use
// std::function instead of absl::AnyInvocable.
std::function<void(AppLifecycleState)> state_updated_callback_;
};
} // namespace api
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APP_LIFECYCLE_MONITOR_H_
@@ -82,6 +82,7 @@ objc_library(
":Platform_cc",
":Shared",
":ble_v2",
":app_lifecycle_monitor",
":network_utils",
# Required Reason API File: third_party/nearby/internal/platform/implementation/apple/preferences_manager.mm
"//releasetools/apple/privacy/privacymanifests/requiredreasonsapi:user_defaults-user_defaults-read_write_app_data_ca92_1",
@@ -115,6 +116,38 @@ objc_library(
}),
)
objc_library(
name = "GNCNotificationCenter",
hdrs = ["GNCNotificationCenter.h"],
deps = [
"//third_party/apple_frameworks:Foundation",
],
)
objc_library(
name = "app_lifecycle_monitor",
srcs = [
"app_lifecycle_monitor.mm",
],
hdrs = [
"app_lifecycle_monitor.h",
],
# Prevent Objective-C++ headers from being pulled into swift.
aspect_hints = ["//tools/build_defs/swift:no_module"],
deps = [
":GNCNotificationCenter",
"//internal/platform:base",
"//internal/platform/implementation:comm",
"//internal/platform/implementation/apple/Log:GNCLogger",
"//third_party/apple_frameworks:Foundation",
] + select({
"@platforms//os:platform_ios": [
"//third_party/apple_frameworks:UIKit",
],
"//conditions:default": [],
}),
)
objc_library(
name = "ble_v2",
srcs = [
@@ -0,0 +1,40 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_GNCNOTIFICATIONCENTER_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_GNCNOTIFICATIONCENTER_H_
#import <Foundation/Foundation.h>
@protocol GNCNotificationCenter <NSObject>
// Method for registering an observer
- (id<NSObject>)addObserverForName:(NSNotificationName)name
object:(id)obj
queue:(NSOperationQueue *)queue
usingBlock:(void (^)(NSNotification *notification))block;
// Method for unregistering an observer
- (void)removeObserver:(id)observer;
// Method for posting a notification
- (void)postNotificationName:(NSNotificationName)aName
object:(nullable id)anObject;
@end
@interface NSNotificationCenter () <GNCNotificationCenter>
@end
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_GNCNOTIFICATIONCENTER_H_
@@ -0,0 +1,46 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_APP_LIFECYCLE_MONITOR_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_APP_LIFECYCLE_MONITOR_H_
#import <Foundation/Foundation.h>
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#import "internal/platform/implementation/apple/GNCNotificationCenter.h"
namespace nearby {
namespace apple {
class AppLifecycleMonitor : public api::AppLifecycleMonitor {
public:
explicit AppLifecycleMonitor(std::function<void(AppLifecycleState)> state_updated_callback);
// Test only.
AppLifecycleMonitor(id<GNCNotificationCenter> notification_center,
std::function<void(AppLifecycleState)> state_updated_callback);
~AppLifecycleMonitor() override;
private:
id<GNCNotificationCenter> notification_center_ = nil;
id<NSObject> active_observer_ = nil;
id<NSObject> inactive_observer_ = nil;
id<NSObject> background_observer_ = nil;
};
} // namespace apple
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_APPLE_APP_LIFECYCLE_MONITOR_H_
@@ -0,0 +1,95 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "internal/platform/implementation/apple/app_lifecycle_monitor.h"
#import <Foundation/Foundation.h>
#include <utility>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#endif // TARGET_OS_IPHONE
#import "internal/platform/implementation/apple/GNCNotificationCenter.h"
#import "internal/platform/implementation/apple/Log/GNCLogger.h"
namespace nearby {
namespace apple {
AppLifecycleMonitor::AppLifecycleMonitor(
std::function<void(AppLifecycleState)> state_updated_callback)
: AppLifecycleMonitor([NSNotificationCenter defaultCenter], std::move(state_updated_callback)) {
}
AppLifecycleMonitor::AppLifecycleMonitor(
id<GNCNotificationCenter> notification_center,
std::function<void(AppLifecycleState)> state_updated_callback)
: api::AppLifecycleMonitor(std::move(state_updated_callback)),
notification_center_(notification_center) {
// Copy the callback to be captured by the blocks below. This avoids capturing `this` in the
// blocks, which would lead to a dangling pointer if `this` is destroyed. The block will hold a
// copy of the callback.
std::function<void(AppLifecycleState)> callback = state_updated_callback_;
#if TARGET_OS_IPHONE
// Register for app lifecycle notifications
background_observer_ =
[notification_center_ addObserverForName:UIApplicationDidEnterBackgroundNotification
object:nil
queue:nil
usingBlock:^(NSNotification *notification) {
GNCLoggerDebug(@"AppLifecycleMonitor: Did enter background.");
if (callback) {
callback(AppLifecycleState::kBackground);
}
}];
inactive_observer_ =
[notification_center_ addObserverForName:UIApplicationWillResignActiveNotification
object:nil
queue:nil
usingBlock:^(NSNotification *notification) {
GNCLoggerDebug(@"AppLifecycleMonitor: Will enter inactive.");
if (callback) {
callback(AppLifecycleState::kInactive);
}
}];
active_observer_ =
[notification_center_ addObserverForName:UIApplicationDidBecomeActiveNotification
object:nil
queue:nil
usingBlock:^(NSNotification *notification) {
GNCLoggerDebug(@"AppLifecycleMonitor: Will enter active.");
if (callback) {
callback(AppLifecycleState::kActive);
}
}];
#else
GNCLoggerError(@"Not implemented");
#endif // TARGET_OS_IPHONE
}
AppLifecycleMonitor::~AppLifecycleMonitor() {
#if TARGET_OS_IPHONE
if (notification_center_) {
[notification_center_ removeObserver:background_observer_];
[notification_center_ removeObserver:active_observer_];
[notification_center_ removeObserver:inactive_observer_];
}
#endif // TARGET_OS_IPHONE
}
} // namespace apple
} // namespace nearby
@@ -16,12 +16,14 @@
#import <Foundation/Foundation.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/strings/string_view.h"
#include "internal/base/files.h"
#import "internal/platform/implementation/apple/Log/GNCLogger.h"
#include "internal/platform/implementation/apple/app_lifecycle_monitor.h"
#include "internal/platform/implementation/apple/atomic_boolean.h"
#include "internal/platform/implementation/apple/atomic_uint32.h"
#include "internal/platform/implementation/apple/awdl.h"
@@ -205,6 +207,15 @@ std::unique_ptr<WifiDirectMedium> ImplementationPlatform::CreateWifiDirectMedium
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() { return nullptr; }
#endif
std::unique_ptr<AppLifecycleMonitor> ImplementationPlatform::CreateAppLifecycleMonitor(
std::function<void(AppLifecycleMonitor::AppLifecycleState)> state_updated_callback) {
#if TARGET_OS_IPHONE
return std::make_unique<apple::AppLifecycleMonitor>(std::move(state_updated_callback));
#else
return nullptr;
#endif
}
absl::StatusOr<WebResponse> ImplementationPlatform::SendRequest(const WebRequest& requestInfo) {
NSURL* url = [NSURL URLWithString:@(requestInfo.url.c_str())];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
@@ -16,6 +16,7 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
@@ -26,6 +27,7 @@
#include "absl/strings/string_view.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/awdl.h"
@@ -184,8 +186,8 @@ ImplementationPlatform::CreateBluetoothClassicMedium(
return std::make_unique<g3::BluetoothClassicMedium>(adapter);
}
std::unique_ptr<api::ble::BleMedium>
ImplementationPlatform::CreateBleMedium(api::BluetoothAdapter& adapter) {
std::unique_ptr<api::ble::BleMedium> ImplementationPlatform::CreateBleMedium(
api::BluetoothAdapter& adapter) {
return std::make_unique<g3::BleMedium>(
dynamic_cast<g3::BluetoothAdapter&>(adapter));
}
@@ -227,6 +229,13 @@ std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
}
#endif
std::unique_ptr<AppLifecycleMonitor>
ImplementationPlatform::CreateAppLifecycleMonitor(
std::function<void(AppLifecycleMonitor::AppLifecycleState)>
state_updated_callback) {
return nullptr;
}
absl::StatusOr<WebResponse> ImplementationPlatform::SendRequest(
const api::WebRequest& request) {
return absl::UnimplementedError("");
+21 -1
View File
@@ -15,12 +15,15 @@
#ifndef PLATFORM_API_PLATFORM_H_
#define PLATFORM_API_PLATFORM_H_
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/awdl.h"
@@ -138,6 +141,18 @@ class ImplementationPlatform {
static std::unique_ptr<WebRtcMedium> CreateWebRtcMedium();
#endif
#if defined(NEARBY_CHROMIUM)
static std::unique_ptr<AppLifecycleMonitor> CreateAppLifecycleMonitor(
std::function<void(AppLifecycleMonitor::AppLifecycleState)>
state_updated_callback) {
return nullptr;
}
#else
static std::unique_ptr<AppLifecycleMonitor> CreateAppLifecycleMonitor(
std::function<void(AppLifecycleMonitor::AppLifecycleState)>
state_updated_callback);
#endif
// Gets HTTP response from remote server.
//
// @param request Webrequest
@@ -147,7 +162,12 @@ class ImplementationPlatform {
// other cases will return absl Status in error.
static absl::StatusOr<WebResponse> SendRequest(const WebRequest& request);
#ifndef NEARBY_CHROMIUM
#if defined(NEARBY_CHROMIUM)
static std::unique_ptr<nearby::api::PreferencesManager>
CreatePreferencesManager(absl::string_view path) {
return nullptr;
}
#else
static std::unique_ptr<nearby::api::PreferencesManager>
CreatePreferencesManager(absl::string_view path);
#endif
@@ -28,11 +28,13 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include "absl/base/attributes.h"
#include "absl/status/statusor.h"
#include "internal/platform/implementation/app_lifecycle_monitor.h"
#undef StrCat // Remove the Windows macro definition
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@@ -290,6 +292,13 @@ std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
return nullptr;
}
std::unique_ptr<AppLifecycleMonitor>
ImplementationPlatform::CreateAppLifecycleMonitor(
std::function<void(AppLifecycleMonitor::AppLifecycleState)>
state_updated_callback) {
return nullptr;
}
absl::StatusOr<WebResponse> ImplementationPlatform::SendRequest(
const WebRequest& request) {
windows::HttpLoader http_loader{request};