• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.util;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.net.SntpClient;
23 import android.os.SystemClock;
24 import android.provider.Settings;
25 
26 /**
27  * {@link TrustedTime} that connects with a remote NTP server as its trusted
28  * time source.
29  *
30  * @hide
31  */
32 public class NtpTrustedTime implements TrustedTime {
33     private static final String TAG = "NtpTrustedTime";
34     private static final boolean LOGD = false;
35 
36     private static NtpTrustedTime sSingleton;
37 
38     private final String mServer;
39     private final long mTimeout;
40 
41     private boolean mHasCache;
42     private long mCachedNtpTime;
43     private long mCachedNtpElapsedRealtime;
44     private long mCachedNtpCertainty;
45 
NtpTrustedTime(String server, long timeout)46     private NtpTrustedTime(String server, long timeout) {
47         if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);
48         mServer = server;
49         mTimeout = timeout;
50     }
51 
getInstance(Context context)52     public static synchronized NtpTrustedTime getInstance(Context context) {
53         if (sSingleton == null) {
54             final Resources res = context.getResources();
55             final ContentResolver resolver = context.getContentResolver();
56 
57             final String defaultServer = res.getString(
58                     com.android.internal.R.string.config_ntpServer);
59             final long defaultTimeout = res.getInteger(
60                     com.android.internal.R.integer.config_ntpTimeout);
61 
62             final String secureServer = Settings.Global.getString(
63                     resolver, Settings.Global.NTP_SERVER);
64             final long timeout = Settings.Global.getLong(
65                     resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout);
66 
67             final String server = secureServer != null ? secureServer : defaultServer;
68             sSingleton = new NtpTrustedTime(server, timeout);
69         }
70 
71         return sSingleton;
72     }
73 
74     @Override
forceRefresh()75     public boolean forceRefresh() {
76         if (mServer == null) {
77             // missing server, so no trusted time available
78             return false;
79         }
80 
81         if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
82         final SntpClient client = new SntpClient();
83         if (client.requestTime(mServer, (int) mTimeout)) {
84             mHasCache = true;
85             mCachedNtpTime = client.getNtpTime();
86             mCachedNtpElapsedRealtime = client.getNtpTimeReference();
87             mCachedNtpCertainty = client.getRoundTripTime() / 2;
88             return true;
89         } else {
90             return false;
91         }
92     }
93 
94     @Override
hasCache()95     public boolean hasCache() {
96         return mHasCache;
97     }
98 
99     @Override
getCacheAge()100     public long getCacheAge() {
101         if (mHasCache) {
102             return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
103         } else {
104             return Long.MAX_VALUE;
105         }
106     }
107 
108     @Override
getCacheCertainty()109     public long getCacheCertainty() {
110         if (mHasCache) {
111             return mCachedNtpCertainty;
112         } else {
113             return Long.MAX_VALUE;
114         }
115     }
116 
117     @Override
currentTimeMillis()118     public long currentTimeMillis() {
119         if (!mHasCache) {
120             throw new IllegalStateException("Missing authoritative time source");
121         }
122         if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
123 
124         // current time is age after the last ntp cache; callers who
125         // want fresh values will hit makeAuthoritative() first.
126         return mCachedNtpTime + getCacheAge();
127     }
128 
getCachedNtpTime()129     public long getCachedNtpTime() {
130         if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
131         return mCachedNtpTime;
132     }
133 
getCachedNtpTimeReference()134     public long getCachedNtpTimeReference() {
135         return mCachedNtpElapsedRealtime;
136     }
137 }
138