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 #include <cstdint>
20 #include <cstdio>
21 #include <cstring>
22 #include <securec.h>
23 #include <unistd.h>
24
25 #include "sntp_client.h"
26 #include "time_common.h"
27
28 namespace OHOS {
29 namespace MiscServices {
30 namespace {
31 constexpr int64_t TIME_RESULT_UNINITED = -1;
32 constexpr int64_t HALF = 2;
33 const int NANO_TO_SECOND = 1000000000;
34 } // namespace
35
GetInstance()36 NtpTrustedTime &NtpTrustedTime::GetInstance()
37 {
38 static NtpTrustedTime instance;
39 return instance;
40 }
41
ForceRefresh(const std::string & ntpServer)42 bool NtpTrustedTime::ForceRefresh(const std::string &ntpServer)
43 {
44 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
45 SNTPClient client;
46 if (client.RequestTime(ntpServer)) {
47 if (mTimeResult != nullptr) {
48 mTimeResult->Clear();
49 }
50 int64_t ntpCertainty = client.getRoundTripTime() / HALF;
51 mTimeResult = std::make_shared<TimeResult>(client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
52 TIME_HILOGD(TIME_MODULE_SERVICE, "Get Ntp time result");
53 return true;
54 }
55 TIME_HILOGD(TIME_MODULE_SERVICE, "false end.");
56 return false;
57 }
58
CurrentTimeMillis()59 int64_t NtpTrustedTime::CurrentTimeMillis()
60 {
61 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
62 if (mTimeResult == nullptr) {
63 TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
64 return TIME_RESULT_UNINITED;
65 }
66 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
67 return mTimeResult->CurrentTimeMillis();
68 }
69
ElapsedRealtimeMillis()70 int64_t NtpTrustedTime::ElapsedRealtimeMillis()
71 {
72 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
73 if (mTimeResult == nullptr) {
74 TIME_HILOGD(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 if (mTimeResult != nullptr) {
84 return std::chrono::duration_cast<std::chrono::milliseconds>(
85 std::chrono::steady_clock::now().time_since_epoch())
86 .count() -
87 mTimeResult->GetElapsedRealtimeMillis();
88 } else {
89 return INT_MAX;
90 }
91 }
92
GetBootTimeNs()93 std::chrono::steady_clock::time_point NtpTrustedTime::GetBootTimeNs()
94 {
95 int64_t timeNow = -1;
96 struct timespec tv {};
97 if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) {
98 return std::chrono::steady_clock::now();
99 }
100 timeNow = tv.tv_sec * NANO_TO_SECOND + tv.tv_nsec;
101 std::chrono::steady_clock::time_point tp_epoch ((std::chrono::nanoseconds(timeNow)));
102 return tp_epoch;
103 }
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 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