| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/forensics/utils/utc_time_provider.h" |
| |
| #include <lib/fit/function.h> |
| |
| #include <optional> |
| |
| #include "src/developer/forensics/utils/time.h" |
| #include "src/lib/files/file.h" |
| |
| namespace forensics { |
| |
| UtcTimeProvider::UtcTimeProvider(UtcClockReadyWatcherBase* utc_clock_ready_watcher, |
| timekeeper::Clock* clock) |
| : UtcTimeProvider(utc_clock_ready_watcher, clock, std::nullopt) {} |
| |
| UtcTimeProvider::UtcTimeProvider(UtcClockReadyWatcherBase* utc_clock_ready_watcher, |
| timekeeper::Clock* clock, |
| PreviousBootFile utc_monotonic_difference_file) |
| : UtcTimeProvider(utc_clock_ready_watcher, clock, |
| std::optional(utc_monotonic_difference_file)) {} |
| |
| UtcTimeProvider::UtcTimeProvider(UtcClockReadyWatcherBase* utc_clock_ready_watcher, |
| timekeeper::Clock* clock, |
| std::optional<PreviousBootFile> utc_monotonic_difference_file) |
| : clock_(clock), |
| utc_monotonic_difference_file_(std::move(utc_monotonic_difference_file)), |
| previous_boot_utc_monotonic_difference_(std::nullopt), |
| utc_clock_ready_watcher_(utc_clock_ready_watcher) { |
| utc_clock_ready_watcher->OnClockReady( |
| fit::bind_member<&UtcTimeProvider::OnClockLoggingQuality>(this)); |
| |
| if (!utc_monotonic_difference_file_.has_value()) { |
| return; |
| } |
| |
| std::string buf; |
| if (!files::ReadFileToString(utc_monotonic_difference_file_.value().PreviousBootPath(), &buf)) { |
| return; |
| } |
| |
| previous_boot_utc_monotonic_difference_ = |
| zx::duration(strtoll(buf.c_str(), nullptr, /*base*/ 10)); |
| } |
| |
| std::optional<timekeeper::time_utc> UtcTimeProvider::CurrentTime() const { |
| if (!utc_clock_ready_watcher_->IsUtcClockReady()) { |
| return std::nullopt; |
| } |
| |
| return CurrentUtcTimeRaw(clock_); |
| } |
| |
| std::optional<zx::duration> UtcTimeProvider::CurrentUtcMonotonicDifference() const { |
| if (!utc_clock_ready_watcher_->IsUtcClockReady()) { |
| return std::nullopt; |
| } |
| |
| const timekeeper::time_utc current_utc_time = CurrentUtcTimeRaw(clock_); |
| const zx::duration utc_monotonic_difference(current_utc_time.get() - clock_->Now().get()); |
| if (utc_monotonic_difference_file_.has_value()) { |
| // Write the most recent UTC-monotonic difference in case either clock has been adjusted. |
| files::WriteFile(utc_monotonic_difference_file_.value().CurrentBootPath(), |
| std::to_string(utc_monotonic_difference.get())); |
| } |
| return utc_monotonic_difference; |
| } |
| |
| std::optional<zx::duration> UtcTimeProvider::PreviousBootUtcMonotonicDifference() const { |
| return previous_boot_utc_monotonic_difference_; |
| } |
| |
| void UtcTimeProvider::OnClockLoggingQuality() { |
| // Write the current difference between the UTC and monotonic clocks. |
| if (utc_monotonic_difference_file_.has_value()) { |
| const timekeeper::time_utc current_utc_time = CurrentUtcTimeRaw(clock_); |
| const zx::duration utc_monotonic_difference(current_utc_time.get() - clock_->Now().get()); |
| files::WriteFile(utc_monotonic_difference_file_.value().CurrentBootPath(), |
| std::to_string(utc_monotonic_difference.get())); |
| } |
| } |
| |
| } // namespace forensics |