1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_POSIX)
14*d9f75844SAndroid Build Coastguard Worker #include <sys/time.h>
15*d9f75844SAndroid Build Coastguard Worker #endif
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
18*d9f75844SAndroid Build Coastguard Worker #include <sys/timeb.h>
19*d9f75844SAndroid Build Coastguard Worker #endif
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system_time.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace rtc {
27*d9f75844SAndroid Build Coastguard Worker
28*d9f75844SAndroid Build Coastguard Worker ClockInterface* g_clock = nullptr;
29*d9f75844SAndroid Build Coastguard Worker
SetClockForTesting(ClockInterface * clock)30*d9f75844SAndroid Build Coastguard Worker ClockInterface* SetClockForTesting(ClockInterface* clock) {
31*d9f75844SAndroid Build Coastguard Worker ClockInterface* prev = g_clock;
32*d9f75844SAndroid Build Coastguard Worker g_clock = clock;
33*d9f75844SAndroid Build Coastguard Worker return prev;
34*d9f75844SAndroid Build Coastguard Worker }
35*d9f75844SAndroid Build Coastguard Worker
GetClockForTesting()36*d9f75844SAndroid Build Coastguard Worker ClockInterface* GetClockForTesting() {
37*d9f75844SAndroid Build Coastguard Worker return g_clock;
38*d9f75844SAndroid Build Coastguard Worker }
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker #if defined(WINUWP)
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker namespace {
43*d9f75844SAndroid Build Coastguard Worker
44*d9f75844SAndroid Build Coastguard Worker class TimeHelper final {
45*d9f75844SAndroid Build Coastguard Worker public:
46*d9f75844SAndroid Build Coastguard Worker TimeHelper(const TimeHelper&) = delete;
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker // Resets the clock based upon an NTP server. This routine must be called
49*d9f75844SAndroid Build Coastguard Worker // prior to the main system start-up to ensure all clocks are based upon
50*d9f75844SAndroid Build Coastguard Worker // an NTP server time if NTP synchronization is required. No critical
51*d9f75844SAndroid Build Coastguard Worker // section is used thus this method must be called prior to any clock
52*d9f75844SAndroid Build Coastguard Worker // routines being used.
SyncWithNtp(int64_t ntp_server_time_ms)53*d9f75844SAndroid Build Coastguard Worker static void SyncWithNtp(int64_t ntp_server_time_ms) {
54*d9f75844SAndroid Build Coastguard Worker auto& singleton = Singleton();
55*d9f75844SAndroid Build Coastguard Worker TIME_ZONE_INFORMATION time_zone;
56*d9f75844SAndroid Build Coastguard Worker GetTimeZoneInformation(&time_zone);
57*d9f75844SAndroid Build Coastguard Worker int64_t time_zone_bias_ns =
58*d9f75844SAndroid Build Coastguard Worker rtc::dchecked_cast<int64_t>(time_zone.Bias) * 60 * 1000 * 1000 * 1000;
59*d9f75844SAndroid Build Coastguard Worker singleton.app_start_time_ns_ =
60*d9f75844SAndroid Build Coastguard Worker (ntp_server_time_ms - kNTPTimeToUnixTimeEpochOffset) * 1000000 -
61*d9f75844SAndroid Build Coastguard Worker time_zone_bias_ns;
62*d9f75844SAndroid Build Coastguard Worker singleton.UpdateReferenceTime();
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker // Returns the number of nanoseconds that have passed since unix epoch.
TicksNs()66*d9f75844SAndroid Build Coastguard Worker static int64_t TicksNs() {
67*d9f75844SAndroid Build Coastguard Worker auto& singleton = Singleton();
68*d9f75844SAndroid Build Coastguard Worker int64_t result = 0;
69*d9f75844SAndroid Build Coastguard Worker LARGE_INTEGER qpcnt;
70*d9f75844SAndroid Build Coastguard Worker QueryPerformanceCounter(&qpcnt);
71*d9f75844SAndroid Build Coastguard Worker result = rtc::dchecked_cast<int64_t>(
72*d9f75844SAndroid Build Coastguard Worker (rtc::dchecked_cast<uint64_t>(qpcnt.QuadPart) * 100000 /
73*d9f75844SAndroid Build Coastguard Worker rtc::dchecked_cast<uint64_t>(singleton.os_ticks_per_second_)) *
74*d9f75844SAndroid Build Coastguard Worker 10000);
75*d9f75844SAndroid Build Coastguard Worker result = singleton.app_start_time_ns_ + result -
76*d9f75844SAndroid Build Coastguard Worker singleton.time_since_os_start_ns_;
77*d9f75844SAndroid Build Coastguard Worker return result;
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker private:
TimeHelper()81*d9f75844SAndroid Build Coastguard Worker TimeHelper() {
82*d9f75844SAndroid Build Coastguard Worker TIME_ZONE_INFORMATION time_zone;
83*d9f75844SAndroid Build Coastguard Worker GetTimeZoneInformation(&time_zone);
84*d9f75844SAndroid Build Coastguard Worker int64_t time_zone_bias_ns =
85*d9f75844SAndroid Build Coastguard Worker rtc::dchecked_cast<int64_t>(time_zone.Bias) * 60 * 1000 * 1000 * 1000;
86*d9f75844SAndroid Build Coastguard Worker FILETIME ft;
87*d9f75844SAndroid Build Coastguard Worker // This will give us system file in UTC format.
88*d9f75844SAndroid Build Coastguard Worker GetSystemTimeAsFileTime(&ft);
89*d9f75844SAndroid Build Coastguard Worker LARGE_INTEGER li;
90*d9f75844SAndroid Build Coastguard Worker li.HighPart = ft.dwHighDateTime;
91*d9f75844SAndroid Build Coastguard Worker li.LowPart = ft.dwLowDateTime;
92*d9f75844SAndroid Build Coastguard Worker
93*d9f75844SAndroid Build Coastguard Worker app_start_time_ns_ = (li.QuadPart - kFileTimeToUnixTimeEpochOffset) * 100 -
94*d9f75844SAndroid Build Coastguard Worker time_zone_bias_ns;
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker UpdateReferenceTime();
97*d9f75844SAndroid Build Coastguard Worker }
98*d9f75844SAndroid Build Coastguard Worker
Singleton()99*d9f75844SAndroid Build Coastguard Worker static TimeHelper& Singleton() {
100*d9f75844SAndroid Build Coastguard Worker static TimeHelper singleton;
101*d9f75844SAndroid Build Coastguard Worker return singleton;
102*d9f75844SAndroid Build Coastguard Worker }
103*d9f75844SAndroid Build Coastguard Worker
UpdateReferenceTime()104*d9f75844SAndroid Build Coastguard Worker void UpdateReferenceTime() {
105*d9f75844SAndroid Build Coastguard Worker LARGE_INTEGER qpfreq;
106*d9f75844SAndroid Build Coastguard Worker QueryPerformanceFrequency(&qpfreq);
107*d9f75844SAndroid Build Coastguard Worker os_ticks_per_second_ = rtc::dchecked_cast<int64_t>(qpfreq.QuadPart);
108*d9f75844SAndroid Build Coastguard Worker
109*d9f75844SAndroid Build Coastguard Worker LARGE_INTEGER qpcnt;
110*d9f75844SAndroid Build Coastguard Worker QueryPerformanceCounter(&qpcnt);
111*d9f75844SAndroid Build Coastguard Worker time_since_os_start_ns_ = rtc::dchecked_cast<int64_t>(
112*d9f75844SAndroid Build Coastguard Worker (rtc::dchecked_cast<uint64_t>(qpcnt.QuadPart) * 100000 /
113*d9f75844SAndroid Build Coastguard Worker rtc::dchecked_cast<uint64_t>(os_ticks_per_second_)) *
114*d9f75844SAndroid Build Coastguard Worker 10000);
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker
117*d9f75844SAndroid Build Coastguard Worker private:
118*d9f75844SAndroid Build Coastguard Worker static constexpr uint64_t kFileTimeToUnixTimeEpochOffset =
119*d9f75844SAndroid Build Coastguard Worker 116444736000000000ULL;
120*d9f75844SAndroid Build Coastguard Worker static constexpr uint64_t kNTPTimeToUnixTimeEpochOffset = 2208988800000L;
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker // The number of nanoseconds since unix system epoch
123*d9f75844SAndroid Build Coastguard Worker int64_t app_start_time_ns_;
124*d9f75844SAndroid Build Coastguard Worker // The number of nanoseconds since the OS started
125*d9f75844SAndroid Build Coastguard Worker int64_t time_since_os_start_ns_;
126*d9f75844SAndroid Build Coastguard Worker // The OS calculated ticks per second
127*d9f75844SAndroid Build Coastguard Worker int64_t os_ticks_per_second_;
128*d9f75844SAndroid Build Coastguard Worker };
129*d9f75844SAndroid Build Coastguard Worker
130*d9f75844SAndroid Build Coastguard Worker } // namespace
131*d9f75844SAndroid Build Coastguard Worker
SyncWithNtp(int64_t time_from_ntp_server_ms)132*d9f75844SAndroid Build Coastguard Worker void SyncWithNtp(int64_t time_from_ntp_server_ms) {
133*d9f75844SAndroid Build Coastguard Worker TimeHelper::SyncWithNtp(time_from_ntp_server_ms);
134*d9f75844SAndroid Build Coastguard Worker }
135*d9f75844SAndroid Build Coastguard Worker
WinUwpSystemTimeNanos()136*d9f75844SAndroid Build Coastguard Worker int64_t WinUwpSystemTimeNanos() {
137*d9f75844SAndroid Build Coastguard Worker return TimeHelper::TicksNs();
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker
140*d9f75844SAndroid Build Coastguard Worker #endif // defined(WINUWP)
141*d9f75844SAndroid Build Coastguard Worker
SystemTimeMillis()142*d9f75844SAndroid Build Coastguard Worker int64_t SystemTimeMillis() {
143*d9f75844SAndroid Build Coastguard Worker return static_cast<int64_t>(SystemTimeNanos() / kNumNanosecsPerMillisec);
144*d9f75844SAndroid Build Coastguard Worker }
145*d9f75844SAndroid Build Coastguard Worker
TimeNanos()146*d9f75844SAndroid Build Coastguard Worker int64_t TimeNanos() {
147*d9f75844SAndroid Build Coastguard Worker if (g_clock) {
148*d9f75844SAndroid Build Coastguard Worker return g_clock->TimeNanos();
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker return SystemTimeNanos();
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker
Time32()153*d9f75844SAndroid Build Coastguard Worker uint32_t Time32() {
154*d9f75844SAndroid Build Coastguard Worker return static_cast<uint32_t>(TimeNanos() / kNumNanosecsPerMillisec);
155*d9f75844SAndroid Build Coastguard Worker }
156*d9f75844SAndroid Build Coastguard Worker
TimeMillis()157*d9f75844SAndroid Build Coastguard Worker int64_t TimeMillis() {
158*d9f75844SAndroid Build Coastguard Worker return TimeNanos() / kNumNanosecsPerMillisec;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
TimeMicros()161*d9f75844SAndroid Build Coastguard Worker int64_t TimeMicros() {
162*d9f75844SAndroid Build Coastguard Worker return TimeNanos() / kNumNanosecsPerMicrosec;
163*d9f75844SAndroid Build Coastguard Worker }
164*d9f75844SAndroid Build Coastguard Worker
TimeAfter(int64_t elapsed)165*d9f75844SAndroid Build Coastguard Worker int64_t TimeAfter(int64_t elapsed) {
166*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_GE(elapsed, 0);
167*d9f75844SAndroid Build Coastguard Worker return TimeMillis() + elapsed;
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker
TimeDiff32(uint32_t later,uint32_t earlier)170*d9f75844SAndroid Build Coastguard Worker int32_t TimeDiff32(uint32_t later, uint32_t earlier) {
171*d9f75844SAndroid Build Coastguard Worker return later - earlier;
172*d9f75844SAndroid Build Coastguard Worker }
173*d9f75844SAndroid Build Coastguard Worker
TimeDiff(int64_t later,int64_t earlier)174*d9f75844SAndroid Build Coastguard Worker int64_t TimeDiff(int64_t later, int64_t earlier) {
175*d9f75844SAndroid Build Coastguard Worker return later - earlier;
176*d9f75844SAndroid Build Coastguard Worker }
177*d9f75844SAndroid Build Coastguard Worker
TimestampWrapAroundHandler()178*d9f75844SAndroid Build Coastguard Worker TimestampWrapAroundHandler::TimestampWrapAroundHandler()
179*d9f75844SAndroid Build Coastguard Worker : last_ts_(0), num_wrap_(-1) {}
180*d9f75844SAndroid Build Coastguard Worker
Unwrap(uint32_t ts)181*d9f75844SAndroid Build Coastguard Worker int64_t TimestampWrapAroundHandler::Unwrap(uint32_t ts) {
182*d9f75844SAndroid Build Coastguard Worker if (num_wrap_ == -1) {
183*d9f75844SAndroid Build Coastguard Worker last_ts_ = ts;
184*d9f75844SAndroid Build Coastguard Worker num_wrap_ = 0;
185*d9f75844SAndroid Build Coastguard Worker return ts;
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker
188*d9f75844SAndroid Build Coastguard Worker if (ts < last_ts_) {
189*d9f75844SAndroid Build Coastguard Worker if (last_ts_ >= 0xf0000000 && ts < 0x0fffffff)
190*d9f75844SAndroid Build Coastguard Worker ++num_wrap_;
191*d9f75844SAndroid Build Coastguard Worker } else if ((ts - last_ts_) > 0xf0000000) {
192*d9f75844SAndroid Build Coastguard Worker // Backwards wrap. Unwrap with last wrap count and don't update last_ts_.
193*d9f75844SAndroid Build Coastguard Worker return ts + (num_wrap_ - 1) * (int64_t{1} << 32);
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker
196*d9f75844SAndroid Build Coastguard Worker last_ts_ = ts;
197*d9f75844SAndroid Build Coastguard Worker return ts + (num_wrap_ << 32);
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker
TmToSeconds(const tm & tm)200*d9f75844SAndroid Build Coastguard Worker int64_t TmToSeconds(const tm& tm) {
201*d9f75844SAndroid Build Coastguard Worker static short int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
202*d9f75844SAndroid Build Coastguard Worker static short int cumul_mdays[12] = {0, 31, 59, 90, 120, 151,
203*d9f75844SAndroid Build Coastguard Worker 181, 212, 243, 273, 304, 334};
204*d9f75844SAndroid Build Coastguard Worker int year = tm.tm_year + 1900;
205*d9f75844SAndroid Build Coastguard Worker int month = tm.tm_mon;
206*d9f75844SAndroid Build Coastguard Worker int day = tm.tm_mday - 1; // Make 0-based like the rest.
207*d9f75844SAndroid Build Coastguard Worker int hour = tm.tm_hour;
208*d9f75844SAndroid Build Coastguard Worker int min = tm.tm_min;
209*d9f75844SAndroid Build Coastguard Worker int sec = tm.tm_sec;
210*d9f75844SAndroid Build Coastguard Worker
211*d9f75844SAndroid Build Coastguard Worker bool expiry_in_leap_year =
212*d9f75844SAndroid Build Coastguard Worker (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
213*d9f75844SAndroid Build Coastguard Worker
214*d9f75844SAndroid Build Coastguard Worker if (year < 1970)
215*d9f75844SAndroid Build Coastguard Worker return -1;
216*d9f75844SAndroid Build Coastguard Worker if (month < 0 || month > 11)
217*d9f75844SAndroid Build Coastguard Worker return -1;
218*d9f75844SAndroid Build Coastguard Worker if (day < 0 || day >= mdays[month] + (expiry_in_leap_year && month == 2 - 1))
219*d9f75844SAndroid Build Coastguard Worker return -1;
220*d9f75844SAndroid Build Coastguard Worker if (hour < 0 || hour > 23)
221*d9f75844SAndroid Build Coastguard Worker return -1;
222*d9f75844SAndroid Build Coastguard Worker if (min < 0 || min > 59)
223*d9f75844SAndroid Build Coastguard Worker return -1;
224*d9f75844SAndroid Build Coastguard Worker if (sec < 0 || sec > 59)
225*d9f75844SAndroid Build Coastguard Worker return -1;
226*d9f75844SAndroid Build Coastguard Worker
227*d9f75844SAndroid Build Coastguard Worker day += cumul_mdays[month];
228*d9f75844SAndroid Build Coastguard Worker
229*d9f75844SAndroid Build Coastguard Worker // Add number of leap days between 1970 and the expiration year, inclusive.
230*d9f75844SAndroid Build Coastguard Worker day += ((year / 4 - 1970 / 4) - (year / 100 - 1970 / 100) +
231*d9f75844SAndroid Build Coastguard Worker (year / 400 - 1970 / 400));
232*d9f75844SAndroid Build Coastguard Worker
233*d9f75844SAndroid Build Coastguard Worker // We will have added one day too much above if expiration is during a leap
234*d9f75844SAndroid Build Coastguard Worker // year, and expiration is in January or February.
235*d9f75844SAndroid Build Coastguard Worker if (expiry_in_leap_year && month <= 2 - 1) // `month` is zero based.
236*d9f75844SAndroid Build Coastguard Worker day -= 1;
237*d9f75844SAndroid Build Coastguard Worker
238*d9f75844SAndroid Build Coastguard Worker // Combine all variables into seconds from 1970-01-01 00:00 (except `month`
239*d9f75844SAndroid Build Coastguard Worker // which was accumulated into `day` above).
240*d9f75844SAndroid Build Coastguard Worker return (((static_cast<int64_t>(year - 1970) * 365 + day) * 24 + hour) * 60 +
241*d9f75844SAndroid Build Coastguard Worker min) *
242*d9f75844SAndroid Build Coastguard Worker 60 +
243*d9f75844SAndroid Build Coastguard Worker sec;
244*d9f75844SAndroid Build Coastguard Worker }
245*d9f75844SAndroid Build Coastguard Worker
TimeUTCMicros()246*d9f75844SAndroid Build Coastguard Worker int64_t TimeUTCMicros() {
247*d9f75844SAndroid Build Coastguard Worker if (g_clock) {
248*d9f75844SAndroid Build Coastguard Worker return g_clock->TimeNanos() / kNumNanosecsPerMicrosec;
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_POSIX)
251*d9f75844SAndroid Build Coastguard Worker struct timeval time;
252*d9f75844SAndroid Build Coastguard Worker gettimeofday(&time, nullptr);
253*d9f75844SAndroid Build Coastguard Worker // Convert from second (1.0) and microsecond (1e-6).
254*d9f75844SAndroid Build Coastguard Worker return (static_cast<int64_t>(time.tv_sec) * rtc::kNumMicrosecsPerSec +
255*d9f75844SAndroid Build Coastguard Worker time.tv_usec);
256*d9f75844SAndroid Build Coastguard Worker
257*d9f75844SAndroid Build Coastguard Worker #elif defined(WEBRTC_WIN)
258*d9f75844SAndroid Build Coastguard Worker struct _timeb time;
259*d9f75844SAndroid Build Coastguard Worker _ftime(&time);
260*d9f75844SAndroid Build Coastguard Worker // Convert from second (1.0) and milliseconds (1e-3).
261*d9f75844SAndroid Build Coastguard Worker return (static_cast<int64_t>(time.time) * rtc::kNumMicrosecsPerSec +
262*d9f75844SAndroid Build Coastguard Worker static_cast<int64_t>(time.millitm) * rtc::kNumMicrosecsPerMillisec);
263*d9f75844SAndroid Build Coastguard Worker #endif
264*d9f75844SAndroid Build Coastguard Worker }
265*d9f75844SAndroid Build Coastguard Worker
TimeUTCMillis()266*d9f75844SAndroid Build Coastguard Worker int64_t TimeUTCMillis() {
267*d9f75844SAndroid Build Coastguard Worker return TimeUTCMicros() / kNumMicrosecsPerMillisec;
268*d9f75844SAndroid Build Coastguard Worker }
269*d9f75844SAndroid Build Coastguard Worker
270*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
271