1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
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
16 #include "ntp_trusted_time.h"
17
18 #include <cinttypes>
19
20 #include "sntp_client.h"
21
22 namespace OHOS {
23 namespace MiscServices {
24 namespace {
25 constexpr int64_t TIME_RESULT_UNINITED = -1;
26 constexpr int64_t HALF = 2;
27 constexpr int NANO_TO_SECOND = 1000000000;
28 constexpr int64_t ONE_DAY = 86400000;
29 } // namespace
30
GetInstance()31 NtpTrustedTime &NtpTrustedTime::GetInstance()
32 {
33 static NtpTrustedTime instance;
34 return instance;
35 }
36
ForceRefresh(const std::string & ntpServer)37 bool NtpTrustedTime::ForceRefresh(const std::string &ntpServer)
38 {
39 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
40 SNTPClient client;
41 if (client.RequestTime(ntpServer)) {
42 if (mTimeResult != nullptr) {
43 mTimeResult->Clear();
44 }
45 int64_t ntpCertainty = client.getRoundTripTime() / HALF;
46 mTimeResult = std::make_shared<TimeResult>(client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
47 TIME_HILOGD(TIME_MODULE_SERVICE, "Get Ntp time result");
48 return true;
49 }
50 TIME_HILOGD(TIME_MODULE_SERVICE, "false end");
51 return false;
52 }
53
CurrentTimeMillis()54 int64_t NtpTrustedTime::CurrentTimeMillis()
55 {
56 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
57 if (mTimeResult == nullptr) {
58 TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
59 return TIME_RESULT_UNINITED;
60 }
61 TIME_HILOGD(TIME_MODULE_SERVICE, "end");
62 return mTimeResult->CurrentTimeMillis();
63 }
64
ElapsedRealtimeMillis()65 int64_t NtpTrustedTime::ElapsedRealtimeMillis()
66 {
67 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
68 if (mTimeResult == nullptr) {
69 TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
70 return TIME_RESULT_UNINITED;
71 }
72 TIME_HILOGD(TIME_MODULE_SERVICE, "end");
73 return mTimeResult->GetElapsedRealtimeMillis();
74 }
75
GetCacheAge()76 int64_t NtpTrustedTime::GetCacheAge()
77 {
78 if (mTimeResult != nullptr) {
79 return std::chrono::duration_cast<std::chrono::milliseconds>(
80 std::chrono::steady_clock::now().time_since_epoch())
81 .count() -
82 mTimeResult->GetElapsedRealtimeMillis();
83 } else {
84 return INT_MAX;
85 }
86 }
87
GetBootTimeNs()88 std::chrono::steady_clock::time_point NtpTrustedTime::GetBootTimeNs()
89 {
90 int64_t timeNow = -1;
91 struct timespec tv {};
92 if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) {
93 return std::chrono::steady_clock::now();
94 }
95 timeNow = tv.tv_sec * NANO_TO_SECOND + tv.tv_nsec;
96 std::chrono::steady_clock::time_point tp_epoch ((std::chrono::nanoseconds(timeNow)));
97 return tp_epoch;
98 }
99
GetTimeMillis()100 int64_t NtpTrustedTime::TimeResult::GetTimeMillis()
101 {
102 return mTimeMillis;
103 }
104
GetElapsedRealtimeMillis()105 int64_t NtpTrustedTime::TimeResult::GetElapsedRealtimeMillis()
106 {
107 return mElapsedRealtimeMillis;
108 }
109
CurrentTimeMillis()110 int64_t NtpTrustedTime::TimeResult::CurrentTimeMillis()
111 {
112 if (mTimeMillis == 0 || mElapsedRealtimeMillis == 0) {
113 TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
114 return TIME_RESULT_UNINITED;
115 }
116 auto bootTime = std::chrono::duration_cast<std::chrono::milliseconds>(
117 NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count();
118 if (static_cast<int64_t>(bootTime) - mElapsedRealtimeMillis > ONE_DAY) {
119 Clear();
120 return TIME_RESULT_UNINITED;
121 }
122 return mTimeMillis + GetAgeMillis();
123 }
124
GetAgeMillis()125 int64_t NtpTrustedTime::TimeResult::GetAgeMillis()
126 {
127 return std::chrono::duration_cast<std::chrono::milliseconds>(
128 NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count() - this->mElapsedRealtimeMillis;
129 }
130
TimeResult()131 NtpTrustedTime::TimeResult::TimeResult()
132 {
133 }
~TimeResult()134 NtpTrustedTime::TimeResult::~TimeResult()
135 {
136 }
137
TimeResult(int64_t mTimeMillis,int64_t mElapsedRealtimeMills,int64_t mCertaintyMillis)138 NtpTrustedTime::TimeResult::TimeResult(int64_t mTimeMillis, int64_t mElapsedRealtimeMills, int64_t mCertaintyMillis)
139 {
140 this->mTimeMillis = mTimeMillis;
141 this->mElapsedRealtimeMillis = mElapsedRealtimeMills;
142 this->mCertaintyMillis = mCertaintyMillis;
143 TIME_HILOGD(TIME_MODULE_SERVICE, "mTimeMillis %{public}" PRId64 "", mTimeMillis);
144 TIME_HILOGD(TIME_MODULE_SERVICE, "mElapsedRealtimeMills %{public}" PRId64 "", mElapsedRealtimeMills);
145 TIME_HILOGD(TIME_MODULE_SERVICE, "mCertaintyMillis %{public}" PRId64 "", mCertaintyMillis);
146 }
147
Clear()148 void NtpTrustedTime::TimeResult::Clear()
149 {
150 mTimeMillis = 0;
151 mElapsedRealtimeMillis = 0;
152 mCertaintyMillis = 0;
153 }
154 } // namespace MiscServices
155 } // namespace OHOS