blob: a4790282dae0a8ef25a0c36ffa99f52dcefb91e2 [file] [log] [blame]
Tianjie Xu98333a82017-09-22 21:29:29 -07001//
2// Copyright (C) 2017 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/metrics_reporter_omaha.h"
18
19#include <memory>
20#include <string>
21
22#include <base/time/time.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
25#include <metrics/metrics_library_mock.h>
26
27#include "update_engine/common/fake_clock.h"
28#include "update_engine/common/fake_prefs.h"
29#include "update_engine/fake_system_state.h"
30
31using base::TimeDelta;
Tianjie Xu98333a82017-09-22 21:29:29 -070032using testing::_;
Marton Hunyadya0302682018-05-16 18:52:13 +020033using testing::AnyNumber;
34using testing::Return;
Tianjie Xu98333a82017-09-22 21:29:29 -070035
36namespace chromeos_update_engine {
37class MetricsReporterOmahaTest : public ::testing::Test {
38 protected:
39 MetricsReporterOmahaTest() = default;
40
41 // Reset the metrics_lib_ to a mock library.
42 void SetUp() override {
43 mock_metrics_lib_ = new testing::NiceMock<MetricsLibraryMock>();
44 reporter_.metrics_lib_.reset(mock_metrics_lib_);
45 }
46
47 testing::NiceMock<MetricsLibraryMock>* mock_metrics_lib_;
48 MetricsReporterOmaha reporter_;
49};
50
51TEST_F(MetricsReporterOmahaTest, ReportDailyMetrics) {
52 TimeDelta age = TimeDelta::FromDays(10);
53 EXPECT_CALL(*mock_metrics_lib_,
54 SendToUMA(metrics::kMetricDailyOSAgeDays, _, _, _, _))
55 .Times(1);
56
57 reporter_.ReportDailyMetrics(age);
58}
59
60TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetrics) {
61 FakeSystemState fake_system_state;
62 FakeClock fake_clock;
63 FakePrefs fake_prefs;
64
65 // We need to execute the report twice to test the time since last report.
66 fake_system_state.set_clock(&fake_clock);
67 fake_system_state.set_prefs(&fake_prefs);
68 fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000));
69 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000));
70
71 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable;
72 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored;
73 metrics::DownloadErrorCode error_code =
74 metrics::DownloadErrorCode::kHttpStatus200;
75
76 EXPECT_CALL(
77 *mock_metrics_lib_,
78 SendEnumToUMA(metrics::kMetricCheckResult, static_cast<int>(result), _))
79 .Times(2);
80 EXPECT_CALL(*mock_metrics_lib_,
81 SendEnumToUMA(
82 metrics::kMetricCheckReaction, static_cast<int>(reaction), _))
83 .Times(2);
84 EXPECT_CALL(*mock_metrics_lib_,
85 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode,
86 static_cast<int>(error_code)))
87 .Times(2);
88
Marton Hunyadya0302682018-05-16 18:52:13 +020089 // Not pinned nor rollback
90 EXPECT_CALL(*mock_metrics_lib_,
91 SendSparseToUMA(metrics::kMetricCheckTargetVersion, _))
92 .Times(0);
93 EXPECT_CALL(*mock_metrics_lib_,
94 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _))
95 .Times(0);
96
Tianjie Xu98333a82017-09-22 21:29:29 -070097 EXPECT_CALL(
98 *mock_metrics_lib_,
99 SendToUMA(metrics::kMetricCheckTimeSinceLastCheckMinutes, 1, _, _, _))
100 .Times(1);
101 EXPECT_CALL(
102 *mock_metrics_lib_,
103 SendToUMA(
104 metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes, 1, _, _, _))
105 .Times(1);
106
107 reporter_.ReportUpdateCheckMetrics(
108 &fake_system_state, result, reaction, error_code);
109
110 // Advance the clock by 1 minute and report the same metrics again.
111 fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000));
112 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000));
Marton Hunyadya0302682018-05-16 18:52:13 +0200113 // Allow rollback
114 reporter_.ReportUpdateCheckMetrics(
115 &fake_system_state, result, reaction, error_code);
116}
117
118TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsPinned) {
119 FakeSystemState fake_system_state;
120
121 OmahaRequestParams params(&fake_system_state);
122 params.set_target_version_prefix("10575.");
123 params.set_rollback_allowed(false);
124 fake_system_state.set_request_params(&params);
125
126 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable;
127 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored;
128 metrics::DownloadErrorCode error_code =
129 metrics::DownloadErrorCode::kHttpStatus200;
130
131 EXPECT_CALL(*mock_metrics_lib_,
132 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _));
133 // Target version set, but not a rollback.
134 EXPECT_CALL(*mock_metrics_lib_,
135 SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575))
136 .Times(1);
137 EXPECT_CALL(*mock_metrics_lib_,
138 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _))
139 .Times(0);
140
141 reporter_.ReportUpdateCheckMetrics(
142 &fake_system_state, result, reaction, error_code);
143}
144
145TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsRollback) {
146 FakeSystemState fake_system_state;
147
148 OmahaRequestParams params(&fake_system_state);
149 params.set_target_version_prefix("10575.");
150 params.set_rollback_allowed(true);
151 fake_system_state.set_request_params(&params);
152
153 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable;
154 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored;
155 metrics::DownloadErrorCode error_code =
156 metrics::DownloadErrorCode::kHttpStatus200;
157
158 EXPECT_CALL(*mock_metrics_lib_,
159 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _));
160 // Rollback.
161 EXPECT_CALL(*mock_metrics_lib_,
162 SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575))
163 .Times(1);
164 EXPECT_CALL(
165 *mock_metrics_lib_,
166 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, 10575))
167 .Times(1);
168
Tianjie Xu98333a82017-09-22 21:29:29 -0700169 reporter_.ReportUpdateCheckMetrics(
170 &fake_system_state, result, reaction, error_code);
171}
172
173TEST_F(MetricsReporterOmahaTest,
174 ReportAbnormallyTerminatedUpdateAttemptMetrics) {
175 EXPECT_CALL(*mock_metrics_lib_,
176 SendEnumToUMA(metrics::kMetricAttemptResult,
177 static_cast<int>(
178 metrics::AttemptResult::kAbnormalTermination),
179 _))
180 .Times(1);
181
182 reporter_.ReportAbnormallyTerminatedUpdateAttemptMetrics();
183}
184
185TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptMetrics) {
186 FakeSystemState fake_system_state;
187 FakeClock fake_clock;
188 FakePrefs fake_prefs;
189
190 fake_system_state.set_clock(&fake_clock);
191 fake_system_state.set_prefs(&fake_prefs);
192 fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000));
193 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000));
194
195 int attempt_number = 1;
196 PayloadType payload_type = kPayloadTypeFull;
197 TimeDelta duration = TimeDelta::FromMinutes(1000);
198 TimeDelta duration_uptime = TimeDelta::FromMinutes(1000);
199
200 int64_t payload_size = 100 * kNumBytesInOneMiB;
Tianjie Xu1f93d092017-10-09 12:13:29 -0700201
Tianjie Xu98333a82017-09-22 21:29:29 -0700202 metrics::AttemptResult attempt_result =
203 metrics::AttemptResult::kInternalError;
204 ErrorCode internal_error_code = ErrorCode::kDownloadInvalidMetadataSignature;
Tianjie Xu98333a82017-09-22 21:29:29 -0700205
206 EXPECT_CALL(*mock_metrics_lib_,
207 SendToUMA(metrics::kMetricAttemptNumber, attempt_number, _, _, _))
208 .Times(2);
209 EXPECT_CALL(*mock_metrics_lib_,
210 SendEnumToUMA(metrics::kMetricAttemptPayloadType,
211 static_cast<int>(payload_type),
212 _))
213 .Times(2);
214 EXPECT_CALL(*mock_metrics_lib_,
215 SendToUMA(metrics::kMetricAttemptDurationMinutes,
216 duration.InMinutes(),
217 _,
218 _,
219 _))
220 .Times(2);
221 EXPECT_CALL(*mock_metrics_lib_,
222 SendToUMA(metrics::kMetricAttemptDurationUptimeMinutes,
223 duration_uptime.InMinutes(),
224 _,
225 _,
226 _))
227 .Times(2);
228
Tianjie Xu98333a82017-09-22 21:29:29 -0700229
230 // Check the report of attempt result.
231 EXPECT_CALL(
232 *mock_metrics_lib_,
233 SendEnumToUMA(
234 metrics::kMetricAttemptResult, static_cast<int>(attempt_result), _))
235 .Times(2);
236 EXPECT_CALL(*mock_metrics_lib_,
237 SendEnumToUMA(metrics::kMetricAttemptInternalErrorCode,
238 static_cast<int>(internal_error_code),
239 _))
240 .Times(2);
241 EXPECT_CALL(*mock_metrics_lib_,
Tianjie Xu1f93d092017-10-09 12:13:29 -0700242 SendToUMA(metrics::kMetricAttemptPayloadSizeMiB, 100, _, _, _))
Tianjie Xu98333a82017-09-22 21:29:29 -0700243 .Times(2);
244
245 // Check the duration between two reports.
246 EXPECT_CALL(
247 *mock_metrics_lib_,
248 SendToUMA(metrics::kMetricAttemptTimeSinceLastAttemptMinutes, 1, _, _, _))
249 .Times(1);
250 EXPECT_CALL(
251 *mock_metrics_lib_,
252 SendToUMA(
253 metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes, 1, _, _, _))
254 .Times(1);
255
Tianjie Xu98333a82017-09-22 21:29:29 -0700256 reporter_.ReportUpdateAttemptMetrics(&fake_system_state,
257 attempt_number,
258 payload_type,
259 duration,
260 duration_uptime,
261 payload_size,
Tianjie Xu98333a82017-09-22 21:29:29 -0700262 attempt_result,
Tianjie Xu1f93d092017-10-09 12:13:29 -0700263 internal_error_code);
Tianjie Xu98333a82017-09-22 21:29:29 -0700264
265 // Advance the clock by 1 minute and report the same metrics again.
266 fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000));
267 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000));
268 reporter_.ReportUpdateAttemptMetrics(&fake_system_state,
269 attempt_number,
270 payload_type,
271 duration,
272 duration_uptime,
273 payload_size,
Tianjie Xu98333a82017-09-22 21:29:29 -0700274 attempt_result,
Tianjie Xu1f93d092017-10-09 12:13:29 -0700275 internal_error_code);
276}
277
278TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptDownloadMetrics) {
279 int64_t payload_bytes_downloaded = 200 * kNumBytesInOneMiB;
280 int64_t payload_download_speed_bps = 100 * 1000;
281 DownloadSource download_source = kDownloadSourceHttpServer;
282 metrics::DownloadErrorCode payload_download_error_code =
283 metrics::DownloadErrorCode::kDownloadError;
284 metrics::ConnectionType connection_type = metrics::ConnectionType::kCellular;
285
286 EXPECT_CALL(
287 *mock_metrics_lib_,
288 SendToUMA(metrics::kMetricAttemptPayloadBytesDownloadedMiB, 200, _, _, _))
289 .Times(1);
290 EXPECT_CALL(
291 *mock_metrics_lib_,
292 SendToUMA(metrics::kMetricAttemptPayloadDownloadSpeedKBps, 100, _, _, _))
293 .Times(1);
294 EXPECT_CALL(*mock_metrics_lib_,
295 SendEnumToUMA(metrics::kMetricAttemptDownloadSource,
296 static_cast<int>(download_source),
297 _))
298 .Times(1);
299 EXPECT_CALL(*mock_metrics_lib_,
300 SendSparseToUMA(metrics::kMetricAttemptDownloadErrorCode,
301 static_cast<int>(payload_download_error_code)))
302 .Times(1);
303 EXPECT_CALL(*mock_metrics_lib_,
304 SendEnumToUMA(metrics::kMetricAttemptConnectionType,
305 static_cast<int>(connection_type),
306 _))
307 .Times(1);
308
309 reporter_.ReportUpdateAttemptDownloadMetrics(payload_bytes_downloaded,
310 payload_download_speed_bps,
311 download_source,
312 payload_download_error_code,
313 connection_type);
Tianjie Xu98333a82017-09-22 21:29:29 -0700314}
315
316TEST_F(MetricsReporterOmahaTest, ReportSuccessfulUpdateMetrics) {
317 int attempt_count = 3;
318 int updates_abandoned_count = 2;
319 PayloadType payload_type = kPayloadTypeDelta;
320 int64_t payload_size = 200 * kNumBytesInOneMiB;
321 int64_t num_bytes_downloaded[kNumDownloadSources] = {};
322 // 200MiB payload downloaded from HttpsServer.
323 num_bytes_downloaded[0] = 200 * kNumBytesInOneMiB;
324 int download_overhead_percentage = 20;
325 TimeDelta total_duration = TimeDelta::FromMinutes(30);
Sen Jiang8712e962018-05-08 12:12:28 -0700326 TimeDelta total_duration_uptime = TimeDelta::FromMinutes(20);
Tianjie Xu98333a82017-09-22 21:29:29 -0700327 int reboot_count = 2;
328 int url_switch_count = 2;
329
330 EXPECT_CALL(
331 *mock_metrics_lib_,
332 SendToUMA(metrics::kMetricSuccessfulUpdatePayloadSizeMiB, 200, _, _, _))
333 .Times(1);
334
335 // Check the report to both BytesDownloadedMiBHttpsServer and
336 // BytesDownloadedMiB
337 std::string DownloadedMiBMetric =
338 metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
339 DownloadedMiBMetric += "HttpsServer";
340 EXPECT_CALL(*mock_metrics_lib_, SendToUMA(DownloadedMiBMetric, 200, _, _, _))
341 .Times(1);
342 EXPECT_CALL(
343 *mock_metrics_lib_,
344 SendToUMA(
345 metrics::kMetricSuccessfulUpdateBytesDownloadedMiB, 200, _, _, _))
346 .Times(1);
347
348 EXPECT_CALL(
349 *mock_metrics_lib_,
350 SendToUMA(
351 metrics::kMetricSuccessfulUpdateDownloadSourcesUsed, 1, _, _, _))
352 .Times(1);
353 EXPECT_CALL(
354 *mock_metrics_lib_,
355 SendToUMA(metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage,
356 20,
357 _,
358 _,
359 _));
360
361 EXPECT_CALL(*mock_metrics_lib_,
362 SendToUMA(metrics::kMetricSuccessfulUpdateUrlSwitchCount,
363 url_switch_count,
364 _,
365 _,
366 _))
367 .Times(1);
368 EXPECT_CALL(
369 *mock_metrics_lib_,
370 SendToUMA(
371 metrics::kMetricSuccessfulUpdateTotalDurationMinutes, 30, _, _, _))
372 .Times(1);
373 EXPECT_CALL(
374 *mock_metrics_lib_,
Sen Jiang8712e962018-05-08 12:12:28 -0700375 SendToUMA(metrics::kMetricSuccessfulUpdateTotalDurationUptimeMinutes,
376 20,
377 _,
378 _,
379 _))
380 .Times(1);
381 EXPECT_CALL(
382 *mock_metrics_lib_,
Tianjie Xu98333a82017-09-22 21:29:29 -0700383 SendToUMA(
384 metrics::kMetricSuccessfulUpdateRebootCount, reboot_count, _, _, _))
385 .Times(1);
386 EXPECT_CALL(*mock_metrics_lib_,
387 SendEnumToUMA(
388 metrics::kMetricSuccessfulUpdatePayloadType, payload_type, _))
389 .Times(1);
390 EXPECT_CALL(
391 *mock_metrics_lib_,
392 SendToUMA(
393 metrics::kMetricSuccessfulUpdateAttemptCount, attempt_count, _, _, _))
394 .Times(1);
395 EXPECT_CALL(*mock_metrics_lib_,
396 SendToUMA(metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount,
397 updates_abandoned_count,
398 _,
399 _,
400 _))
401 .Times(1);
402
403 reporter_.ReportSuccessfulUpdateMetrics(attempt_count,
404 updates_abandoned_count,
405 payload_type,
406 payload_size,
407 num_bytes_downloaded,
408 download_overhead_percentage,
409 total_duration,
Sen Jiang8712e962018-05-08 12:12:28 -0700410 total_duration_uptime,
Tianjie Xu98333a82017-09-22 21:29:29 -0700411 reboot_count,
412 url_switch_count);
413}
414
415TEST_F(MetricsReporterOmahaTest, ReportRollbackMetrics) {
416 metrics::RollbackResult result = metrics::RollbackResult::kSuccess;
417 EXPECT_CALL(*mock_metrics_lib_,
418 SendEnumToUMA(
419 metrics::kMetricRollbackResult, static_cast<int>(result), _))
420 .Times(1);
421
422 reporter_.ReportRollbackMetrics(result);
423}
424
Marton Hunyadya0302682018-05-16 18:52:13 +0200425TEST_F(MetricsReporterOmahaTest, ReportEnterpriseRollbackMetrics) {
426 EXPECT_CALL(*mock_metrics_lib_,
427 SendSparseToUMA(metrics::kMetricEnterpriseRollbackSuccess, 10575))
428 .Times(1);
429 EXPECT_CALL(*mock_metrics_lib_,
430 SendSparseToUMA(metrics::kMetricEnterpriseRollbackFailure, 10323))
431 .Times(1);
432
433 reporter_.ReportEnterpriseRollbackMetrics(/*success=*/true, "10575.39.2");
434 reporter_.ReportEnterpriseRollbackMetrics(/*success=*/false, "10323.67.7");
435}
436
Tianjie Xu98333a82017-09-22 21:29:29 -0700437TEST_F(MetricsReporterOmahaTest, ReportCertificateCheckMetrics) {
438 ServerToCheck server_to_check = ServerToCheck::kUpdate;
439 CertificateCheckResult result = CertificateCheckResult::kValid;
440 EXPECT_CALL(*mock_metrics_lib_,
441 SendEnumToUMA(metrics::kMetricCertificateCheckUpdateCheck,
442 static_cast<int>(result),
443 _))
444 .Times(1);
445
446 reporter_.ReportCertificateCheckMetrics(server_to_check, result);
447}
448
449TEST_F(MetricsReporterOmahaTest, ReportFailedUpdateCount) {
450 int target_attempt = 3;
451 EXPECT_CALL(
452 *mock_metrics_lib_,
453 SendToUMA(metrics::kMetricFailedUpdateCount, target_attempt, _, _, _))
454 .Times(1);
455
456 reporter_.ReportFailedUpdateCount(target_attempt);
457}
458
459TEST_F(MetricsReporterOmahaTest, ReportTimeToReboot) {
460 int time_to_reboot_minutes = 1000;
461 EXPECT_CALL(
462 *mock_metrics_lib_,
463 SendToUMA(
464 metrics::kMetricTimeToRebootMinutes, time_to_reboot_minutes, _, _, _))
465 .Times(1);
466
467 reporter_.ReportTimeToReboot(time_to_reboot_minutes);
468}
469
470TEST_F(MetricsReporterOmahaTest, ReportInstallDateProvisioningSource) {
471 int source = 2;
472 int max = 5;
473 EXPECT_CALL(
474 *mock_metrics_lib_,
475 SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource, source, max))
476 .Times(1);
477
478 reporter_.ReportInstallDateProvisioningSource(source, max);
479}
480
Marton Hunyadyffbfdfb2018-05-30 13:03:29 +0200481TEST_F(MetricsReporterOmahaTest, ReportKeyVersionMetrics) {
482 int kernel_min_version = 0x00040002;
483 int kernel_max_rollforward_version = 0xfffffffe;
484 bool kernel_max_rollforward_success = true;
485 EXPECT_CALL(
486 *mock_metrics_lib_,
487 SendSparseToUMA(metrics::kMetricKernelMinVersion, kernel_min_version))
488 .Times(1);
489 EXPECT_CALL(*mock_metrics_lib_,
490 SendSparseToUMA(metrics::kMetricKernelMaxRollforwardVersion,
491 kernel_max_rollforward_version))
492 .Times(1);
493 EXPECT_CALL(*mock_metrics_lib_,
494 SendBoolToUMA(metrics::kMetricKernelMaxRollforwardSetSuccess,
495 kernel_max_rollforward_success))
496 .Times(1);
497
498 reporter_.ReportKeyVersionMetrics(kernel_min_version,
499 kernel_max_rollforward_version,
500 kernel_max_rollforward_success);
501}
502
May Lippert60aa3ca2018-08-15 16:55:29 -0700503TEST_F(MetricsReporterOmahaTest, ReportEnterpriseUpdateSeenToDownloadDays) {
504 constexpr int kDaysToUpdate = 10;
505 constexpr int kMinBucket = 1;
506 constexpr int kMaxBucket = 6 * 30; // approximately 6 months
507 constexpr int kNumBuckets = 50;
508
509 EXPECT_CALL(*mock_metrics_lib_,
510 SendToUMA(metrics::kMetricSuccessfulUpdateDurationFromSeenDays,
511 kDaysToUpdate,
512 kMinBucket,
513 kMaxBucket,
514 kNumBuckets))
515 .Times(1);
516
517 reporter_.ReportEnterpriseUpdateSeenToDownloadDays(
518 false /* has_time_restriction_policy */, kDaysToUpdate);
519}
520
521TEST_F(MetricsReporterOmahaTest,
522 ReportEnterpriseTimeRestrictedUpdateSeenToDownloadTime) {
523 const int kDaysToUpdate = 15;
524 constexpr int kMinBucket = 1;
525 constexpr int kMaxBucket = 6 * 30; // approximately 6 months
526 constexpr int kNumBuckets = 50;
527
528 EXPECT_CALL(
529 *mock_metrics_lib_,
530 SendToUMA(
531 metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays,
532 kDaysToUpdate,
533 kMinBucket,
534 kMaxBucket,
535 kNumBuckets))
536 .Times(1);
537
538 reporter_.ReportEnterpriseUpdateSeenToDownloadDays(
539 true /* has_time_restriction_policy */, kDaysToUpdate);
540}
541
Tianjie Xu98333a82017-09-22 21:29:29 -0700542} // namespace chromeos_update_engine