FPRNanoPbUtils.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "FirebasePerformance/Sources/FPRNanoPbUtils.h"
  15. #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
  16. #import <CoreTelephony/CTCarrier.h>
  17. #import <CoreTelephony/CTTelephonyNetworkInfo.h>
  18. #endif
  19. #import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
  20. #import "FirebasePerformance/Sources/Common/FPRConstants.h"
  21. #import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
  22. #import "FirebasePerformance/Sources/FPRDataUtils.h"
  23. #import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
  24. #import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
  25. #import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
  26. #import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
  27. #import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
  28. #define BYTES_TO_KB(x) (x / 1024)
  29. static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
  30. NSString *methodString);
  31. #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
  32. static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void);
  33. #endif
  34. NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions);
  35. #pragma mark - Nanopb creation utilities
  36. /** Converts the network method string to a value defined in the enum
  37. * firebase_perf_v1_NetworkRequestMetric_HttpMethod.
  38. * @return Enum value of the method string. If there is no mapping value defined for the method
  39. * firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN is returned.
  40. */
  41. static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
  42. NSString *methodString) {
  43. static NSDictionary<NSString *, NSNumber *> *HTTPToFPRNetworkTraceMethod;
  44. static dispatch_once_t onceToken = 0;
  45. dispatch_once(&onceToken, ^{
  46. HTTPToFPRNetworkTraceMethod = @{
  47. @"GET" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_GET),
  48. @"POST" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_POST),
  49. @"PUT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PUT),
  50. @"DELETE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_DELETE),
  51. @"HEAD" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_HEAD),
  52. @"PATCH" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PATCH),
  53. @"OPTIONS" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_OPTIONS),
  54. @"TRACE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_TRACE),
  55. @"CONNECT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_CONNECT),
  56. };
  57. });
  58. NSNumber *HTTPMethod = HTTPToFPRNetworkTraceMethod[methodString];
  59. if (HTTPMethod == nil) {
  60. return firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN;
  61. }
  62. return HTTPMethod.intValue;
  63. }
  64. #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
  65. /** Get the current cellular network connection type in
  66. * firebase_perf_v1_NetworkConnectionInfo_MobileSubtype format.
  67. * @return Current cellular network connection type.
  68. */
  69. static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void) {
  70. static NSDictionary<NSString *, NSNumber *> *cellularNetworkToMobileSubtype;
  71. static dispatch_once_t onceToken = 0;
  72. dispatch_once(&onceToken, ^{
  73. cellularNetworkToMobileSubtype = @{
  74. CTRadioAccessTechnologyGPRS : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_GPRS),
  75. CTRadioAccessTechnologyEdge : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EDGE),
  76. CTRadioAccessTechnologyWCDMA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
  77. CTRadioAccessTechnologyHSDPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSDPA),
  78. CTRadioAccessTechnologyHSUPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSUPA),
  79. CTRadioAccessTechnologyCDMA1x : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
  80. CTRadioAccessTechnologyCDMAEVDORev0 :
  81. @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_0),
  82. CTRadioAccessTechnologyCDMAEVDORevA :
  83. @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_A),
  84. CTRadioAccessTechnologyCDMAEVDORevB :
  85. @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_B),
  86. CTRadioAccessTechnologyeHRPD : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EHRPD),
  87. CTRadioAccessTechnologyLTE : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_LTE)
  88. };
  89. });
  90. // Use recent APIs for iOS 12 and above and older APIs for before.
  91. if (@available(iOS 12, *)) {
  92. NSDictionary<NSString *, NSString *> *radioAccessors =
  93. FPRNetworkInfo().serviceCurrentRadioAccessTechnology;
  94. if (radioAccessors.count > 0) {
  95. NSString *networkString = [radioAccessors.allValues objectAtIndex:0];
  96. NSNumber *cellularNetworkType = cellularNetworkToMobileSubtype[networkString];
  97. return cellularNetworkType.intValue;
  98. }
  99. } else {
  100. #pragma clang diagnostic push
  101. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  102. NSString *networkString = FPRNetworkInfo().currentRadioAccessTechnology;
  103. #pragma clang diagnostic pop
  104. NSNumber *cellularNetworkType = cellularNetworkToMobileSubtype[networkString];
  105. return cellularNetworkType.intValue;
  106. }
  107. return firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
  108. }
  109. #endif
  110. #pragma mark - Nanopb decode and encode helper methods
  111. pb_bytes_array_t *FPREncodeData(NSData *data) {
  112. pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
  113. if (pbBytesArray != NULL) {
  114. [data getBytes:pbBytesArray->bytes length:data.length];
  115. pbBytesArray->size = (pb_size_t)data.length;
  116. }
  117. return pbBytesArray;
  118. }
  119. pb_bytes_array_t *FPREncodeString(NSString *string) {
  120. NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
  121. return FPREncodeData(stringBytes);
  122. }
  123. StringToStringMap *_Nullable FPREncodeStringToStringMap(NSDictionary *_Nullable dict) {
  124. StringToStringMap *map = calloc(dict.count, sizeof(StringToStringMap));
  125. __block NSUInteger index = 0;
  126. [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
  127. map[index].key = FPREncodeString(key);
  128. map[index].value = FPREncodeString(value);
  129. index++;
  130. }];
  131. return map;
  132. }
  133. StringToNumberMap *_Nullable FPREncodeStringToNumberMap(NSDictionary *_Nullable dict) {
  134. StringToNumberMap *map = calloc(dict.count, sizeof(StringToNumberMap));
  135. __block NSUInteger index = 0;
  136. [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *value, BOOL *stop) {
  137. map[index].key = FPREncodeString(key);
  138. map[index].value = [value longLongValue];
  139. map[index].has_value = true;
  140. index++;
  141. }];
  142. return map;
  143. }
  144. firebase_perf_v1_PerfSession *FPREncodePerfSessions(NSArray<FPRSessionDetails *> *sessions,
  145. NSInteger count) {
  146. firebase_perf_v1_PerfSession *perfSessions = calloc(count, sizeof(firebase_perf_v1_PerfSession));
  147. __block NSUInteger perfSessionIndex = 0;
  148. [sessions enumerateObjectsUsingBlock:^(FPRSessionDetails *_Nonnull session, NSUInteger index,
  149. BOOL *_Nonnull stop) {
  150. perfSessions[perfSessionIndex].session_id = FPREncodeString(session.sessionId);
  151. perfSessions[perfSessionIndex].session_verbosity_count = 0;
  152. if ((session.options & FPRSessionOptionsEvents) ||
  153. (session.options & FPRSessionOptionsGauges)) {
  154. perfSessions[perfSessionIndex].session_verbosity_count = 1;
  155. perfSessions[perfSessionIndex].session_verbosity =
  156. calloc(perfSessions[perfSessionIndex].session_verbosity_count,
  157. sizeof(firebase_perf_v1_SessionVerbosity));
  158. perfSessions[perfSessionIndex].session_verbosity[0] =
  159. firebase_perf_v1_SessionVerbosity_GAUGES_AND_SYSTEM_EVENTS;
  160. }
  161. perfSessionIndex++;
  162. }];
  163. return perfSessions;
  164. }
  165. #pragma mark - Public methods
  166. firebase_perf_v1_PerfMetric FPRGetPerfMetricMessage(NSString *appID) {
  167. firebase_perf_v1_PerfMetric perfMetricMessage = firebase_perf_v1_PerfMetric_init_default;
  168. FPRSetApplicationInfo(&perfMetricMessage, FPRGetApplicationInfoMessage());
  169. perfMetricMessage.application_info.google_app_id = FPREncodeString(appID);
  170. return perfMetricMessage;
  171. }
  172. firebase_perf_v1_ApplicationInfo FPRGetApplicationInfoMessage(void) {
  173. firebase_perf_v1_ApplicationInfo appInfoMessage = firebase_perf_v1_ApplicationInfo_init_default;
  174. firebase_perf_v1_IosApplicationInfo iosAppInfo = firebase_perf_v1_IosApplicationInfo_init_default;
  175. NSBundle *mainBundle = [NSBundle mainBundle];
  176. iosAppInfo.bundle_short_version =
  177. FPREncodeString([mainBundle infoDictionary][@"CFBundleShortVersionString"]);
  178. iosAppInfo.sdk_version = FPREncodeString([NSString stringWithUTF8String:kFPRSDKVersion]);
  179. iosAppInfo.network_connection_info.network_type =
  180. [FPRAppActivityTracker sharedInstance].networkType;
  181. iosAppInfo.has_network_connection_info = true;
  182. iosAppInfo.network_connection_info.has_network_type = true;
  183. #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
  184. if (iosAppInfo.network_connection_info.network_type ==
  185. firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE) {
  186. iosAppInfo.network_connection_info.mobile_subtype = FPRCellularNetworkType();
  187. iosAppInfo.network_connection_info.has_mobile_subtype = true;
  188. }
  189. #endif
  190. appInfoMessage.ios_app_info = iosAppInfo;
  191. appInfoMessage.has_ios_app_info = true;
  192. NSDictionary<NSString *, NSString *> *attributes =
  193. [[FIRPerformance sharedInstance].attributes mutableCopy];
  194. appInfoMessage.custom_attributes_count = (pb_size_t)attributes.count;
  195. appInfoMessage.custom_attributes =
  196. (firebase_perf_v1_ApplicationInfo_CustomAttributesEntry *)FPREncodeStringToStringMap(
  197. attributes);
  198. return appInfoMessage;
  199. }
  200. firebase_perf_v1_TraceMetric FPRGetTraceMetric(FIRTrace *trace) {
  201. firebase_perf_v1_TraceMetric traceMetric = firebase_perf_v1_TraceMetric_init_default;
  202. traceMetric.name = FPREncodeString(trace.name);
  203. // Set if the trace is an internally created trace.
  204. traceMetric.is_auto = trace.isInternal;
  205. traceMetric.has_is_auto = true;
  206. // Convert the trace duration from seconds to microseconds.
  207. traceMetric.duration_us = trace.totalTraceTimeInterval * USEC_PER_SEC;
  208. traceMetric.has_duration_us = true;
  209. // Convert the start time from seconds to microseconds.
  210. traceMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
  211. traceMetric.has_client_start_time_us = true;
  212. // Filling counters
  213. NSDictionary<NSString *, NSNumber *> *counters = trace.counters;
  214. traceMetric.counters_count = (pb_size_t)counters.count;
  215. traceMetric.counters =
  216. (firebase_perf_v1_TraceMetric_CountersEntry *)FPREncodeStringToNumberMap(counters);
  217. // Filling subtraces
  218. traceMetric.subtraces_count = (pb_size_t)[trace.stages count];
  219. firebase_perf_v1_TraceMetric *subtraces =
  220. calloc(traceMetric.subtraces_count, sizeof(firebase_perf_v1_TraceMetric));
  221. __block NSUInteger subtraceIndex = 0;
  222. [trace.stages
  223. enumerateObjectsUsingBlock:^(FIRTrace *_Nonnull stage, NSUInteger idx, BOOL *_Nonnull stop) {
  224. subtraces[subtraceIndex] = FPRGetTraceMetric(stage);
  225. subtraceIndex++;
  226. }];
  227. traceMetric.subtraces = subtraces;
  228. // Filling custom attributes
  229. NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
  230. traceMetric.custom_attributes_count = (pb_size_t)attributes.count;
  231. traceMetric.custom_attributes =
  232. (firebase_perf_v1_TraceMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(attributes);
  233. // Filling session details
  234. NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
  235. traceMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
  236. traceMetric.perf_sessions =
  237. FPREncodePerfSessions(orderedSessions, traceMetric.perf_sessions_count);
  238. return traceMetric;
  239. }
  240. firebase_perf_v1_NetworkRequestMetric FPRGetNetworkRequestMetric(FPRNetworkTrace *trace) {
  241. firebase_perf_v1_NetworkRequestMetric networkMetric =
  242. firebase_perf_v1_NetworkRequestMetric_init_default;
  243. networkMetric.url = FPREncodeString(trace.trimmedURLString);
  244. networkMetric.http_method = FPRHTTPMethodForString(trace.URLRequest.HTTPMethod);
  245. networkMetric.has_http_method = true;
  246. // Convert the start time from seconds to microseconds.
  247. networkMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
  248. networkMetric.has_client_start_time_us = true;
  249. networkMetric.request_payload_bytes = trace.requestSize;
  250. networkMetric.has_request_payload_bytes = true;
  251. networkMetric.response_payload_bytes = trace.responseSize;
  252. networkMetric.has_response_payload_bytes = true;
  253. networkMetric.http_response_code = trace.responseCode;
  254. networkMetric.has_http_response_code = true;
  255. networkMetric.response_content_type = FPREncodeString(trace.responseContentType);
  256. if (trace.responseError) {
  257. networkMetric.network_client_error_reason =
  258. firebase_perf_v1_NetworkRequestMetric_NetworkClientErrorReason_GENERIC_CLIENT_ERROR;
  259. networkMetric.has_network_client_error_reason = true;
  260. }
  261. NSTimeInterval requestTimeUs =
  262. USEC_PER_SEC *
  263. [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  264. andState:FPRNetworkTraceCheckpointStateRequestCompleted];
  265. if (requestTimeUs > 0) {
  266. networkMetric.time_to_request_completed_us = requestTimeUs;
  267. networkMetric.has_time_to_request_completed_us = true;
  268. }
  269. NSTimeInterval responseIntiationTimeUs =
  270. USEC_PER_SEC *
  271. [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  272. andState:FPRNetworkTraceCheckpointStateResponseReceived];
  273. if (responseIntiationTimeUs > 0) {
  274. networkMetric.time_to_response_initiated_us = responseIntiationTimeUs;
  275. networkMetric.has_time_to_response_initiated_us = true;
  276. }
  277. NSTimeInterval responseCompletedUs =
  278. USEC_PER_SEC *
  279. [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  280. andState:FPRNetworkTraceCheckpointStateResponseCompleted];
  281. if (responseCompletedUs > 0) {
  282. networkMetric.time_to_response_completed_us = responseCompletedUs;
  283. networkMetric.has_time_to_response_completed_us = true;
  284. }
  285. // Filling custom attributes
  286. NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
  287. networkMetric.custom_attributes_count = (pb_size_t)attributes.count;
  288. networkMetric.custom_attributes =
  289. (firebase_perf_v1_NetworkRequestMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(
  290. attributes);
  291. // Filling session details
  292. NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
  293. networkMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
  294. networkMetric.perf_sessions =
  295. FPREncodePerfSessions(orderedSessions, networkMetric.perf_sessions_count);
  296. return networkMetric;
  297. }
  298. firebase_perf_v1_GaugeMetric FPRGetGaugeMetric(NSArray *gaugeData, NSString *sessionId) {
  299. firebase_perf_v1_GaugeMetric gaugeMetric = firebase_perf_v1_GaugeMetric_init_default;
  300. gaugeMetric.session_id = FPREncodeString(sessionId);
  301. __block NSInteger cpuReadingsCount = 0;
  302. __block NSInteger memoryReadingsCount = 0;
  303. firebase_perf_v1_CpuMetricReading *cpuReadings =
  304. calloc([gaugeData count], sizeof(firebase_perf_v1_CpuMetricReading));
  305. firebase_perf_v1_IosMemoryReading *memoryReadings =
  306. calloc([gaugeData count], sizeof(firebase_perf_v1_IosMemoryReading));
  307. [gaugeData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  308. if ([obj isKindOfClass:[FPRCPUGaugeData class]]) {
  309. FPRCPUGaugeData *gaugeData = (FPRCPUGaugeData *)obj;
  310. cpuReadings[cpuReadingsCount].client_time_us =
  311. gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
  312. cpuReadings[cpuReadingsCount].has_client_time_us = true;
  313. cpuReadings[cpuReadingsCount].system_time_us = gaugeData.systemTime;
  314. cpuReadings[cpuReadingsCount].has_system_time_us = true;
  315. cpuReadings[cpuReadingsCount].user_time_us = gaugeData.userTime;
  316. cpuReadings[cpuReadingsCount].has_user_time_us = true;
  317. cpuReadingsCount++;
  318. }
  319. if ([obj isKindOfClass:[FPRMemoryGaugeData class]]) {
  320. FPRMemoryGaugeData *gaugeData = (FPRMemoryGaugeData *)obj;
  321. memoryReadings[memoryReadingsCount].client_time_us =
  322. gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
  323. memoryReadings[memoryReadingsCount].has_client_time_us = true;
  324. memoryReadings[memoryReadingsCount].used_app_heap_memory_kb =
  325. (int32_t)BYTES_TO_KB(gaugeData.heapUsed);
  326. memoryReadings[memoryReadingsCount].has_used_app_heap_memory_kb = true;
  327. memoryReadings[memoryReadingsCount].free_app_heap_memory_kb =
  328. (int32_t)BYTES_TO_KB(gaugeData.heapAvailable);
  329. memoryReadings[memoryReadingsCount].has_free_app_heap_memory_kb = true;
  330. memoryReadingsCount++;
  331. }
  332. }];
  333. cpuReadings = realloc(cpuReadings, cpuReadingsCount * sizeof(firebase_perf_v1_CpuMetricReading));
  334. memoryReadings =
  335. realloc(memoryReadings, memoryReadingsCount * sizeof(firebase_perf_v1_IosMemoryReading));
  336. gaugeMetric.cpu_metric_readings = cpuReadings;
  337. gaugeMetric.cpu_metric_readings_count = (pb_size_t)cpuReadingsCount;
  338. gaugeMetric.ios_memory_readings = memoryReadings;
  339. gaugeMetric.ios_memory_readings_count = (pb_size_t)memoryReadingsCount;
  340. return gaugeMetric;
  341. }
  342. firebase_perf_v1_ApplicationProcessState FPRApplicationProcessState(FPRTraceState state) {
  343. firebase_perf_v1_ApplicationProcessState processState =
  344. firebase_perf_v1_ApplicationProcessState_APPLICATION_PROCESS_STATE_UNKNOWN;
  345. switch (state) {
  346. case FPRTraceStateForegroundOnly:
  347. processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND;
  348. break;
  349. case FPRTraceStateBackgroundOnly:
  350. processState = firebase_perf_v1_ApplicationProcessState_BACKGROUND;
  351. break;
  352. case FPRTraceStateBackgroundAndForeground:
  353. processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND_BACKGROUND;
  354. break;
  355. default:
  356. break;
  357. }
  358. return processState;
  359. }
  360. #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
  361. CTTelephonyNetworkInfo *FPRNetworkInfo(void) {
  362. static CTTelephonyNetworkInfo *networkInfo;
  363. static dispatch_once_t onceToken;
  364. dispatch_once(&onceToken, ^{
  365. networkInfo = [[CTTelephonyNetworkInfo alloc] init];
  366. });
  367. return networkInfo;
  368. }
  369. #endif
  370. /** Reorders the list of sessions to make sure the first session is verbose if at least one session
  371. * in the list is verbose.
  372. * @return Ordered list of sessions.
  373. */
  374. NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions) {
  375. NSMutableArray<FPRSessionDetails *> *orderedSessions =
  376. [[NSMutableArray<FPRSessionDetails *> alloc] initWithArray:sessions];
  377. NSInteger firstVerboseSessionIndex = -1;
  378. for (int i = 0; i < [sessions count]; i++) {
  379. if ([sessions[i] isVerbose]) {
  380. firstVerboseSessionIndex = i;
  381. break;
  382. }
  383. }
  384. if (firstVerboseSessionIndex > 0) {
  385. FPRSessionDetails *verboseSession = orderedSessions[firstVerboseSessionIndex];
  386. [orderedSessions removeObjectAtIndex:firstVerboseSessionIndex];
  387. [orderedSessions insertObject:verboseSession atIndex:0];
  388. }
  389. return [orderedSessions copy];
  390. }
  391. #pragma mark - Nanopb struct fields populating helper methods
  392. void FPRSetApplicationInfo(firebase_perf_v1_PerfMetric *perfMetric,
  393. firebase_perf_v1_ApplicationInfo appInfo) {
  394. perfMetric->application_info = appInfo;
  395. perfMetric->has_application_info = true;
  396. }
  397. void FPRSetTraceMetric(firebase_perf_v1_PerfMetric *perfMetric,
  398. firebase_perf_v1_TraceMetric traceMetric) {
  399. perfMetric->trace_metric = traceMetric;
  400. perfMetric->has_trace_metric = true;
  401. }
  402. void FPRSetNetworkRequestMetric(firebase_perf_v1_PerfMetric *perfMetric,
  403. firebase_perf_v1_NetworkRequestMetric networkMetric) {
  404. perfMetric->network_request_metric = networkMetric;
  405. perfMetric->has_network_request_metric = true;
  406. }
  407. void FPRSetGaugeMetric(firebase_perf_v1_PerfMetric *perfMetric,
  408. firebase_perf_v1_GaugeMetric gaugeMetric) {
  409. perfMetric->gauge_metric = gaugeMetric;
  410. perfMetric->has_gauge_metric = true;
  411. }
  412. void FPRSetApplicationProcessState(firebase_perf_v1_PerfMetric *perfMetric,
  413. firebase_perf_v1_ApplicationProcessState state) {
  414. perfMetric->application_info.application_process_state = state;
  415. perfMetric->application_info.has_application_process_state = true;
  416. }