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