Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 
15
#import "FirebasePerformance/Sources/FPRNanoPbUtils.h"
16
 
17
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
18
#import <CoreTelephony/CTCarrier.h>
19
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
20
#endif
21
#import <SystemConfiguration/SystemConfiguration.h>
22
 
23
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
24
#import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
25
#import "FirebasePerformance/Sources/FPRDataUtils.h"
26
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
27
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
28
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
29
 
30
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
31
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
32
 
33
#define BYTES_TO_KB(x) (x / 1024)
34
 
35
static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
36
    NSString *methodString);
37
static firebase_perf_v1_NetworkConnectionInfo_NetworkType FPRNetworkConnectionInfoNetworkType(void);
38
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
39
static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void);
40
#endif
41
NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions);
42
 
43
#pragma mark - Nanopb creation utilities
44
 
45
/** Converts the network method string to a value defined in the enum
46
 *  firebase_perf_v1_NetworkRequestMetric_HttpMethod.
47
 *  @return Enum value of the method string. If there is no mapping value defined for the method
48
 * firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN is returned.
49
 */
50
static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
51
    NSString *methodString) {
52
  static NSDictionary<NSString *, NSNumber *> *HTTPToFPRNetworkTraceMethod;
53
  static dispatch_once_t onceToken = 0;
54
  dispatch_once(&onceToken, ^{
55
    HTTPToFPRNetworkTraceMethod = @{
56
      @"GET" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_GET),
57
      @"POST" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_POST),
58
      @"PUT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PUT),
59
      @"DELETE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_DELETE),
60
      @"HEAD" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_HEAD),
61
      @"PATCH" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PATCH),
62
      @"OPTIONS" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_OPTIONS),
63
      @"TRACE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_TRACE),
64
      @"CONNECT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_CONNECT),
65
    };
66
  });
67
 
68
  NSNumber *HTTPMethod = HTTPToFPRNetworkTraceMethod[methodString];
69
  if (HTTPMethod == nil) {
70
    return firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN;
71
  }
72
  return HTTPMethod.intValue;
73
}
74
 
75
/** Get the current network connection type in firebase_perf_v1_NetworkConnectionInfo_NetworkType
76
 * format.
77
 *  @return Current network connection type.
78
 */
79
static firebase_perf_v1_NetworkConnectionInfo_NetworkType FPRNetworkConnectionInfoNetworkType() {
80
  firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType =
81
      firebase_perf_v1_NetworkConnectionInfo_NetworkType_NONE;
82
 
83
  static SCNetworkReachabilityRef reachabilityRef = 0;
84
  static dispatch_once_t onceToken;
85
  dispatch_once(&onceToken, ^{
86
    reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorSystemDefault, "google.com");
87
  });
88
 
89
  SCNetworkReachabilityFlags reachabilityFlags = 0;
90
  SCNetworkReachabilityGetFlags(reachabilityRef, &reachabilityFlags);
91
 
92
  // Parse the network flags to set the network type.
93
  if (reachabilityFlags & kSCNetworkReachabilityFlagsReachable) {
94
    if (reachabilityFlags & kSCNetworkReachabilityFlagsIsWWAN) {
95
      networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE;
96
    } else {
97
      networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_WIFI;
98
    }
99
  }
100
 
101
  return networkType;
102
}
103
 
104
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
105
/** Get the current cellular network connection type in
106
 * firebase_perf_v1_NetworkConnectionInfo_MobileSubtype format.
107
 *  @return Current cellular network connection type.
108
 */
109
static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType() {
110
  static NSDictionary<NSString *, NSNumber *> *cellularNetworkToMobileSubtype;
111
  static dispatch_once_t onceToken = 0;
112
  dispatch_once(&onceToken, ^{
113
    cellularNetworkToMobileSubtype = @{
114
      CTRadioAccessTechnologyGPRS : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_GPRS),
115
      CTRadioAccessTechnologyEdge : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EDGE),
116
      CTRadioAccessTechnologyWCDMA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
117
      CTRadioAccessTechnologyHSDPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSDPA),
118
      CTRadioAccessTechnologyHSUPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSUPA),
119
      CTRadioAccessTechnologyCDMA1x : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
120
      CTRadioAccessTechnologyCDMAEVDORev0 :
121
          @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_0),
122
      CTRadioAccessTechnologyCDMAEVDORevA :
123
          @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_A),
124
      CTRadioAccessTechnologyCDMAEVDORevB :
125
          @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_B),
126
      CTRadioAccessTechnologyeHRPD : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EHRPD),
127
      CTRadioAccessTechnologyLTE : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_LTE)
128
    };
129
  });
130
 
131
  NSString *networkString = FPRNetworkInfo().currentRadioAccessTechnology;
132
  NSNumber *cellularNetworkType = cellularNetworkToMobileSubtype[networkString];
133
  return cellularNetworkType.intValue;
134
}
135
#endif
136
 
137
#pragma mark - Nanopb decode and encode helper methods
138
 
139
pb_bytes_array_t *FPREncodeData(NSData *data) {
140
  pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
141
  if (pbBytesArray != NULL) {
142
    [data getBytes:pbBytesArray->bytes length:data.length];
143
    pbBytesArray->size = (pb_size_t)data.length;
144
  }
145
  return pbBytesArray;
146
}
147
 
148
pb_bytes_array_t *FPREncodeString(NSString *string) {
149
  NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
150
  return FPREncodeData(stringBytes);
151
}
152
 
153
StringToStringMap *_Nullable FPREncodeStringToStringMap(NSDictionary *_Nullable dict) {
154
  StringToStringMap *map = calloc(dict.count, sizeof(StringToStringMap));
155
  __block NSUInteger index = 0;
156
  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
157
    map[index].key = FPREncodeString(key);
158
    map[index].value = FPREncodeString(value);
159
    index++;
160
  }];
161
  return map;
162
}
163
 
164
StringToNumberMap *_Nullable FPREncodeStringToNumberMap(NSDictionary *_Nullable dict) {
165
  StringToNumberMap *map = calloc(dict.count, sizeof(StringToNumberMap));
166
  __block NSUInteger index = 0;
167
  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *value, BOOL *stop) {
168
    map[index].key = FPREncodeString(key);
169
    map[index].value = [value longLongValue];
170
    map[index].has_value = true;
171
    index++;
172
  }];
173
  return map;
174
}
175
 
176
firebase_perf_v1_PerfSession *FPREncodePerfSessions(NSArray<FPRSessionDetails *> *sessions,
177
                                                    NSInteger count) {
178
  firebase_perf_v1_PerfSession *perfSessions = calloc(count, sizeof(firebase_perf_v1_PerfSession));
179
  __block NSUInteger perfSessionIndex = 0;
180
 
181
  [sessions enumerateObjectsUsingBlock:^(FPRSessionDetails *_Nonnull session, NSUInteger index,
182
                                         BOOL *_Nonnull stop) {
183
    perfSessions[perfSessionIndex].session_id = FPREncodeString(session.sessionId);
184
    perfSessions[perfSessionIndex].session_verbosity_count = 0;
185
    if ((session.options & FPRSessionOptionsEvents) ||
186
        (session.options & FPRSessionOptionsGauges)) {
187
      perfSessions[perfSessionIndex].session_verbosity_count = 1;
188
      perfSessions[perfSessionIndex].session_verbosity =
189
          calloc(perfSessions[perfSessionIndex].session_verbosity_count,
190
                 sizeof(firebase_perf_v1_SessionVerbosity));
191
      perfSessions[perfSessionIndex].session_verbosity[0] =
192
          firebase_perf_v1_SessionVerbosity_GAUGES_AND_SYSTEM_EVENTS;
193
    }
194
    perfSessionIndex++;
195
  }];
196
  return perfSessions;
197
}
198
 
199
#pragma mark - Public methods
200
 
201
firebase_perf_v1_PerfMetric FPRGetPerfMetricMessage(NSString *appID) {
202
  firebase_perf_v1_PerfMetric perfMetricMessage = firebase_perf_v1_PerfMetric_init_default;
203
  FPRSetApplicationInfo(&perfMetricMessage, FPRGetApplicationInfoMessage());
204
  perfMetricMessage.application_info.google_app_id = FPREncodeString(appID);
205
 
206
  return perfMetricMessage;
207
}
208
 
209
firebase_perf_v1_ApplicationInfo FPRGetApplicationInfoMessage() {
210
  firebase_perf_v1_ApplicationInfo appInfoMessage = firebase_perf_v1_ApplicationInfo_init_default;
211
  firebase_perf_v1_IosApplicationInfo iosAppInfo = firebase_perf_v1_IosApplicationInfo_init_default;
212
  NSBundle *mainBundle = [NSBundle mainBundle];
213
  iosAppInfo.bundle_short_version =
214
      FPREncodeString([mainBundle infoDictionary][@"CFBundleShortVersionString"]);
215
  iosAppInfo.sdk_version = FPREncodeString([NSString stringWithUTF8String:kFPRSDKVersion]);
216
  iosAppInfo.network_connection_info.network_type = FPRNetworkConnectionInfoNetworkType();
217
  iosAppInfo.has_network_connection_info = true;
218
  iosAppInfo.network_connection_info.has_network_type = true;
219
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
220
  CTTelephonyNetworkInfo *networkInfo = FPRNetworkInfo();
221
  CTCarrier *provider = networkInfo.subscriberCellularProvider;
222
  NSString *mccMnc = FPRValidatedMccMnc(provider.mobileCountryCode, provider.mobileNetworkCode);
223
  if (mccMnc) {
224
    iosAppInfo.mcc_mnc = FPREncodeString(mccMnc);
225
  }
226
  if (iosAppInfo.network_connection_info.network_type ==
227
      firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE) {
228
    iosAppInfo.network_connection_info.mobile_subtype = FPRCellularNetworkType();
229
    iosAppInfo.network_connection_info.has_mobile_subtype = true;
230
  }
231
#endif
232
  appInfoMessage.ios_app_info = iosAppInfo;
233
  appInfoMessage.has_ios_app_info = true;
234
 
235
  NSDictionary<NSString *, NSString *> *attributes =
236
      [[FIRPerformance sharedInstance].attributes mutableCopy];
237
  appInfoMessage.custom_attributes_count = (pb_size_t)attributes.count;
238
  appInfoMessage.custom_attributes =
239
      (firebase_perf_v1_ApplicationInfo_CustomAttributesEntry *)FPREncodeStringToStringMap(
240
          attributes);
241
 
242
  return appInfoMessage;
243
}
244
 
245
firebase_perf_v1_TraceMetric FPRGetTraceMetric(FIRTrace *trace) {
246
  firebase_perf_v1_TraceMetric traceMetric = firebase_perf_v1_TraceMetric_init_default;
247
  traceMetric.name = FPREncodeString(trace.name);
248
 
249
  // Set if the trace is an internally created trace.
250
  traceMetric.is_auto = trace.isInternal;
251
  traceMetric.has_is_auto = true;
252
 
253
  // Convert the trace duration from seconds to microseconds.
254
  traceMetric.duration_us = trace.totalTraceTimeInterval * USEC_PER_SEC;
255
  traceMetric.has_duration_us = true;
256
 
257
  // Convert the start time from seconds to microseconds.
258
  traceMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
259
  traceMetric.has_client_start_time_us = true;
260
 
261
  // Filling counters
262
  NSDictionary<NSString *, NSNumber *> *counters = trace.counters;
263
  traceMetric.counters_count = (pb_size_t)counters.count;
264
  traceMetric.counters =
265
      (firebase_perf_v1_TraceMetric_CountersEntry *)FPREncodeStringToNumberMap(counters);
266
 
267
  // Filling subtraces
268
  traceMetric.subtraces_count = (pb_size_t)[trace.stages count];
269
  firebase_perf_v1_TraceMetric *subtraces =
270
      calloc(traceMetric.subtraces_count, sizeof(firebase_perf_v1_TraceMetric));
271
  __block NSUInteger subtraceIndex = 0;
272
  [trace.stages
273
      enumerateObjectsUsingBlock:^(FIRTrace *_Nonnull stage, NSUInteger idx, BOOL *_Nonnull stop) {
274
        subtraces[subtraceIndex] = FPRGetTraceMetric(stage);
275
        subtraceIndex++;
276
      }];
277
  traceMetric.subtraces = subtraces;
278
 
279
  // Filling custom attributes
280
  NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
281
  traceMetric.custom_attributes_count = (pb_size_t)attributes.count;
282
  traceMetric.custom_attributes =
283
      (firebase_perf_v1_TraceMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(attributes);
284
 
285
  // Filling session details
286
  NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
287
  traceMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
288
  traceMetric.perf_sessions =
289
      FPREncodePerfSessions(orderedSessions, traceMetric.perf_sessions_count);
290
 
291
  return traceMetric;
292
}
293
 
294
firebase_perf_v1_NetworkRequestMetric FPRGetNetworkRequestMetric(FPRNetworkTrace *trace) {
295
  firebase_perf_v1_NetworkRequestMetric networkMetric =
296
      firebase_perf_v1_NetworkRequestMetric_init_default;
297
  networkMetric.url = FPREncodeString(trace.trimmedURLString);
298
  networkMetric.http_method = FPRHTTPMethodForString(trace.URLRequest.HTTPMethod);
299
  networkMetric.has_http_method = true;
300
 
301
  // Convert the start time from seconds to microseconds.
302
  networkMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
303
  networkMetric.has_client_start_time_us = true;
304
 
305
  networkMetric.request_payload_bytes = trace.requestSize;
306
  networkMetric.has_request_payload_bytes = true;
307
  networkMetric.response_payload_bytes = trace.responseSize;
308
  networkMetric.has_response_payload_bytes = true;
309
 
310
  networkMetric.http_response_code = trace.responseCode;
311
  networkMetric.has_http_response_code = true;
312
  networkMetric.response_content_type = FPREncodeString(trace.responseContentType);
313
 
314
  if (trace.responseError) {
315
    networkMetric.network_client_error_reason =
316
        firebase_perf_v1_NetworkRequestMetric_NetworkClientErrorReason_GENERIC_CLIENT_ERROR;
317
    networkMetric.has_network_client_error_reason = true;
318
  }
319
 
320
  NSTimeInterval requestTimeUs =
321
      USEC_PER_SEC *
322
      [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
323
                                       andState:FPRNetworkTraceCheckpointStateRequestCompleted];
324
  if (requestTimeUs > 0) {
325
    networkMetric.time_to_request_completed_us = requestTimeUs;
326
    networkMetric.has_time_to_request_completed_us = true;
327
  }
328
 
329
  NSTimeInterval responseIntiationTimeUs =
330
      USEC_PER_SEC *
331
      [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
332
                                       andState:FPRNetworkTraceCheckpointStateResponseReceived];
333
  if (responseIntiationTimeUs > 0) {
334
    networkMetric.time_to_response_initiated_us = responseIntiationTimeUs;
335
    networkMetric.has_time_to_response_initiated_us = true;
336
  }
337
 
338
  NSTimeInterval responseCompletedUs =
339
      USEC_PER_SEC *
340
      [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
341
                                       andState:FPRNetworkTraceCheckpointStateResponseCompleted];
342
  if (responseCompletedUs > 0) {
343
    networkMetric.time_to_response_completed_us = responseCompletedUs;
344
    networkMetric.has_time_to_response_completed_us = true;
345
  }
346
 
347
  // Filling custom attributes
348
  NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
349
  networkMetric.custom_attributes_count = (pb_size_t)attributes.count;
350
  networkMetric.custom_attributes =
351
      (firebase_perf_v1_NetworkRequestMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(
352
          attributes);
353
 
354
  // Filling session details
355
  NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
356
  networkMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
357
  networkMetric.perf_sessions =
358
      FPREncodePerfSessions(orderedSessions, networkMetric.perf_sessions_count);
359
 
360
  return networkMetric;
361
}
362
 
363
firebase_perf_v1_GaugeMetric FPRGetGaugeMetric(NSArray *gaugeData, NSString *sessionId) {
364
  firebase_perf_v1_GaugeMetric gaugeMetric = firebase_perf_v1_GaugeMetric_init_default;
365
  gaugeMetric.session_id = FPREncodeString(sessionId);
366
 
367
  __block NSInteger cpuReadingsCount = 0;
368
  __block NSInteger memoryReadingsCount = 0;
369
 
370
  firebase_perf_v1_CpuMetricReading *cpuReadings =
371
      calloc([gaugeData count], sizeof(firebase_perf_v1_CpuMetricReading));
372
  firebase_perf_v1_IosMemoryReading *memoryReadings =
373
      calloc([gaugeData count], sizeof(firebase_perf_v1_IosMemoryReading));
374
  [gaugeData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
375
    if ([obj isKindOfClass:[FPRCPUGaugeData class]]) {
376
      FPRCPUGaugeData *gaugeData = (FPRCPUGaugeData *)obj;
377
      cpuReadings[cpuReadingsCount].client_time_us =
378
          gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
379
      cpuReadings[cpuReadingsCount].has_client_time_us = true;
380
      cpuReadings[cpuReadingsCount].system_time_us = gaugeData.systemTime;
381
      cpuReadings[cpuReadingsCount].has_system_time_us = true;
382
      cpuReadings[cpuReadingsCount].user_time_us = gaugeData.userTime;
383
      cpuReadings[cpuReadingsCount].has_user_time_us = true;
384
      cpuReadingsCount++;
385
    }
386
 
387
    if ([obj isKindOfClass:[FPRMemoryGaugeData class]]) {
388
      FPRMemoryGaugeData *gaugeData = (FPRMemoryGaugeData *)obj;
389
      memoryReadings[memoryReadingsCount].client_time_us =
390
          gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
391
      memoryReadings[memoryReadingsCount].has_client_time_us = true;
392
      memoryReadings[memoryReadingsCount].used_app_heap_memory_kb =
393
          (int32_t)BYTES_TO_KB(gaugeData.heapUsed);
394
      memoryReadings[memoryReadingsCount].has_used_app_heap_memory_kb = true;
395
      memoryReadings[memoryReadingsCount].free_app_heap_memory_kb =
396
          (int32_t)BYTES_TO_KB(gaugeData.heapAvailable);
397
      memoryReadings[memoryReadingsCount].has_free_app_heap_memory_kb = true;
398
      memoryReadingsCount++;
399
    }
400
  }];
401
  cpuReadings = realloc(cpuReadings, cpuReadingsCount * sizeof(firebase_perf_v1_CpuMetricReading));
402
  memoryReadings =
403
      realloc(memoryReadings, memoryReadingsCount * sizeof(firebase_perf_v1_IosMemoryReading));
404
 
405
  gaugeMetric.cpu_metric_readings = cpuReadings;
406
  gaugeMetric.cpu_metric_readings_count = (pb_size_t)cpuReadingsCount;
407
  gaugeMetric.ios_memory_readings = memoryReadings;
408
  gaugeMetric.ios_memory_readings_count = (pb_size_t)memoryReadingsCount;
409
  return gaugeMetric;
410
}
411
 
412
firebase_perf_v1_ApplicationProcessState FPRApplicationProcessState(FPRTraceState state) {
413
  firebase_perf_v1_ApplicationProcessState processState =
414
      firebase_perf_v1_ApplicationProcessState_APPLICATION_PROCESS_STATE_UNKNOWN;
415
  switch (state) {
416
    case FPRTraceStateForegroundOnly:
417
      processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND;
418
      break;
419
 
420
    case FPRTraceStateBackgroundOnly:
421
      processState = firebase_perf_v1_ApplicationProcessState_BACKGROUND;
422
      break;
423
 
424
    case FPRTraceStateBackgroundAndForeground:
425
      processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND_BACKGROUND;
426
      break;
427
 
428
    default:
429
      break;
430
  }
431
 
432
  return processState;
433
}
434
 
435
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
436
CTTelephonyNetworkInfo *FPRNetworkInfo() {
437
  static CTTelephonyNetworkInfo *networkInfo;
438
  static dispatch_once_t onceToken;
439
  dispatch_once(&onceToken, ^{
440
    networkInfo = [[CTTelephonyNetworkInfo alloc] init];
441
  });
442
  return networkInfo;
443
}
444
#endif
445
 
446
/** Reorders the list of sessions to make sure the first session is verbose if at least one session
447
 *  in the list is verbose.
448
 *  @return Ordered list of sessions.
449
 */
450
NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions) {
451
  NSMutableArray<FPRSessionDetails *> *orderedSessions =
452
      [[NSMutableArray<FPRSessionDetails *> alloc] initWithArray:sessions];
453
 
454
  NSInteger firstVerboseSessionIndex = -1;
455
  for (int i = 0; i < [sessions count]; i++) {
456
    if ([sessions[i] isVerbose]) {
457
      firstVerboseSessionIndex = i;
458
      break;
459
    }
460
  }
461
 
462
  if (firstVerboseSessionIndex > 0) {
463
    FPRSessionDetails *verboseSession = orderedSessions[firstVerboseSessionIndex];
464
    [orderedSessions removeObjectAtIndex:firstVerboseSessionIndex];
465
    [orderedSessions insertObject:verboseSession atIndex:0];
466
  }
467
 
468
  return [orderedSessions copy];
469
}
470
 
471
#pragma mark - Nanopb struct fields populating helper methods
472
 
473
void FPRSetApplicationInfo(firebase_perf_v1_PerfMetric *perfMetric,
474
                           firebase_perf_v1_ApplicationInfo appInfo) {
475
  perfMetric->application_info = appInfo;
476
  perfMetric->has_application_info = true;
477
}
478
 
479
void FPRSetTraceMetric(firebase_perf_v1_PerfMetric *perfMetric,
480
                       firebase_perf_v1_TraceMetric traceMetric) {
481
  perfMetric->trace_metric = traceMetric;
482
  perfMetric->has_trace_metric = true;
483
}
484
 
485
void FPRSetNetworkRequestMetric(firebase_perf_v1_PerfMetric *perfMetric,
486
                                firebase_perf_v1_NetworkRequestMetric networkMetric) {
487
  perfMetric->network_request_metric = networkMetric;
488
  perfMetric->has_network_request_metric = true;
489
}
490
 
491
void FPRSetGaugeMetric(firebase_perf_v1_PerfMetric *perfMetric,
492
                       firebase_perf_v1_GaugeMetric gaugeMetric) {
493
  perfMetric->gauge_metric = gaugeMetric;
494
  perfMetric->has_gauge_metric = true;
495
}
496
 
497
void FPRSetApplicationProcessState(firebase_perf_v1_PerfMetric *perfMetric,
498
                                   firebase_perf_v1_ApplicationProcessState state) {
499
  perfMetric->application_info.application_process_state = state;
500
  perfMetric->application_info.has_application_process_state = true;
501
}