Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace SystemConfiguration with a more recent Apple provided network monitoring API. #13091

Merged
merged 13 commits into from
Jun 7, 2024
Merged
1 change: 0 additions & 1 deletion FirebasePerformance.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ Firebase Performance library to measure performance of Mobile and Web Apps.

s.ios.framework = 'CoreTelephony'
s.framework = 'QuartzCore'
s.framework = 'SystemConfiguration'
visumickey marked this conversation as resolved.
Show resolved Hide resolved
s.dependency 'FirebaseCore', '~> 10.5'
s.dependency 'FirebaseInstallations', '~> 10.0'
s.dependency 'FirebaseRemoteConfig', '~> 10.0'
Expand Down
1 change: 1 addition & 0 deletions FirebasePerformance/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased
- Fix Crash from InstrumentUploadTaskWithStreamedRequest (#12983).
- Replace SystemConfiguration with a more available network monitoring API by Apple (#13079).

# 10.25.0
- [changed] Removed usages of user defaults API to eliminate required reason impact.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#import "FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h"
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRTrace.h"

FOUNDATION_EXTERN NSString *__nonnull const kFPRAppStartTraceName;
Expand Down Expand Up @@ -50,6 +51,9 @@ NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions."
/** Current running state of the application. */
@property(nonatomic, readonly) FPRApplicationState applicationState;

/** Current network connection type of the application. */
@property(nonatomic, readonly) firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType;

/** Accesses the singleton instance.
* @return Reference to the shared object if successful; <code>nil</code> if not.
*/
Expand Down
59 changes: 56 additions & 3 deletions FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"

#import <Foundation/Foundation.h>
#import <Network/Network.h>
#import <UIKit/UIKit.h>

#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
Expand Down Expand Up @@ -55,6 +56,15 @@ @interface FPRAppActivityTracker ()
/** Current running state of the application. */
@property(nonatomic, readwrite) FPRApplicationState applicationState;

/** Current network connection type of the application. */
@property(nonatomic, readwrite) firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType;

/** Network monitor object to track network movements. */
@property(nonatomic, readwrite) nw_path_monitor_t monitor;

/** Queue used to track the network monitoring changes. */
@property(nonatomic, readwrite) dispatch_queue_t monitorQueue;

/** Trace to measure the app start performance. */
@property(nonatomic) FIRTrace *appStartTrace;

Expand Down Expand Up @@ -122,9 +132,12 @@ + (instancetype)sharedInstance {
*/
- (instancetype)initAppActivityTracker {
self = [super init];
_applicationState = FPRApplicationStateUnknown;
_appStartGaugeMetricDispatched = NO;
_configurations = [FPRConfigurations sharedInstance];
if (self != nil) {
_applicationState = FPRApplicationStateUnknown;
_appStartGaugeMetricDispatched = NO;
_configurations = [FPRConfigurations sharedInstance];
[self startTrackingNetwork];
}
return self;
}

Expand All @@ -147,6 +160,38 @@ - (FIRTrace *)activeTrace {
return self.backgroundSessionTrace;
}

- (void)startTrackingNetwork {
self.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_NONE;

#if TARGET_OS_IOS
visumickey marked this conversation as resolved.
Show resolved Hide resolved
if (@available(iOS 12, *)) {
#elif TARGET_OS_TVOS
if (@available(tvOS 12, *)) {
#endif
dispatch_queue_attr_t attrs = dispatch_queue_attr_make_with_qos_class(
DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, DISPATCH_QUEUE_PRIORITY_DEFAULT);
self.monitorQueue = dispatch_queue_create("com.google.perf.network.monitor", attrs);
visumickey marked this conversation as resolved.
Show resolved Hide resolved

self.monitor = nw_path_monitor_create();
nw_path_monitor_set_queue(self.monitor, self.monitorQueue);
nw_path_monitor_set_update_handler(self.monitor, ^(nw_path_t _Nonnull path) {
BOOL isWiFi = nw_path_uses_interface_type(path, nw_interface_type_wifi);
visumickey marked this conversation as resolved.
Show resolved Hide resolved
BOOL isCellular = nw_path_uses_interface_type(path, nw_interface_type_cellular);
BOOL isEthernet = nw_path_uses_interface_type(path, nw_interface_type_wired);

if (isWiFi) {
self.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_WIFI;
} else if (isCellular) {
self.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE;
} else if (isEthernet) {
self.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_ETHERNET;
}
});

nw_path_monitor_start(self.monitor);
}
}

/**
* Checks if the prewarming feature is available on the current device.
*
Expand Down Expand Up @@ -286,6 +331,14 @@ - (void)appWillResignActiveNotification:(NSNotification *)notification {
}

- (void)dealloc {
#if TARGET_OS_IOS
if (@available(iOS 12, *)) {
visumickey marked this conversation as resolved.
Show resolved Hide resolved
#elif TARGET_OS_TVOS
if (@available(tvOS 12, *)) {
#endif
nw_path_monitor_cancel(self.monitor);
}

[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
Expand Down
36 changes: 3 additions & 33 deletions FirebasePerformance/Sources/FPRNanoPbUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#endif
#import <SystemConfiguration/SystemConfiguration.h>

#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
#import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
#import "FirebasePerformance/Sources/FPRDataUtils.h"
Expand All @@ -34,7 +34,6 @@

static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
NSString *methodString);
static firebase_perf_v1_NetworkConnectionInfo_NetworkType FPRNetworkConnectionInfoNetworkType(void);
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void);
#endif
Expand Down Expand Up @@ -72,36 +71,6 @@ static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
return HTTPMethod.intValue;
}

/** Get the current network connection type in firebase_perf_v1_NetworkConnectionInfo_NetworkType
* format.
* @return Current network connection type.
*/
static firebase_perf_v1_NetworkConnectionInfo_NetworkType FPRNetworkConnectionInfoNetworkType(
void) {
firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType =
firebase_perf_v1_NetworkConnectionInfo_NetworkType_NONE;

static SCNetworkReachabilityRef reachabilityRef = 0;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorSystemDefault, "google.com");
});

SCNetworkReachabilityFlags reachabilityFlags = 0;
SCNetworkReachabilityGetFlags(reachabilityRef, &reachabilityFlags);

// Parse the network flags to set the network type.
if (reachabilityFlags & kSCNetworkReachabilityFlagsReachable) {
if (reachabilityFlags & kSCNetworkReachabilityFlagsIsWWAN) {
networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE;
} else {
networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_WIFI;
}
}

return networkType;
}

#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
/** Get the current cellular network connection type in
* firebase_perf_v1_NetworkConnectionInfo_MobileSubtype format.
Expand Down Expand Up @@ -233,7 +202,8 @@ firebase_perf_v1_ApplicationInfo FPRGetApplicationInfoMessage(void) {
iosAppInfo.bundle_short_version =
FPREncodeString([mainBundle infoDictionary][@"CFBundleShortVersionString"]);
iosAppInfo.sdk_version = FPREncodeString([NSString stringWithUTF8String:kFPRSDKVersion]);
iosAppInfo.network_connection_info.network_type = FPRNetworkConnectionInfoNetworkType();
iosAppInfo.network_connection_info.network_type =
[FPRAppActivityTracker sharedInstance].networkType;
iosAppInfo.has_network_connection_info = true;
iosAppInfo.network_connection_info.has_network_type = true;
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
Expand Down
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,6 @@ let package = Package(
.define("FIRPerformance_LIB_VERSION", to: firebaseVersion),
],
linkerSettings: [
.linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .tvOS])),
.linkedFramework("MobileCoreServices", .when(platforms: [.iOS, .tvOS])),
.linkedFramework("QuartzCore", .when(platforms: [.iOS, .tvOS])),
]
Expand Down
Loading