• 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.annotation.UnsupportedAppUsage;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.net.ConnectivityManager;
24 import android.net.Network;
25 import android.net.NetworkInfo;
26 import android.net.SntpClient;
27 import android.os.SystemClock;
28 import android.provider.Settings;
29 import android.text.TextUtils;
30 
31 /**
32  * {@link TrustedTime} that connects with a remote NTP server as its trusted
33  * time source.
34  *
35  * @hide
36  */
37 public class NtpTrustedTime implements TrustedTime {
38     private static final String TAG = "NtpTrustedTime";
39     private static final boolean LOGD = false;
40 
41     private static NtpTrustedTime sSingleton;
42     private static Context sContext;
43 
44     private final String mServer;
45     private final long mTimeout;
46 
47     private ConnectivityManager mCM;
48 
49     private boolean mHasCache;
50     private long mCachedNtpTime;
51     private long mCachedNtpElapsedRealtime;
52     private long mCachedNtpCertainty;
53 
NtpTrustedTime(String server, long timeout)54     private NtpTrustedTime(String server, long timeout) {
55         if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);
56         mServer = server;
57         mTimeout = timeout;
58     }
59 
60     @UnsupportedAppUsage
getInstance(Context context)61     public static synchronized NtpTrustedTime getInstance(Context context) {
62         if (sSingleton == null) {
63             final Resources res = context.getResources();
64             final ContentResolver resolver = context.getContentResolver();
65 
66             final String defaultServer = res.getString(
67                     com.android.internal.R.string.config_ntpServer);
68             final long defaultTimeout = res.getInteger(
69                     com.android.internal.R.integer.config_ntpTimeout);
70 
71             final String secureServer = Settings.Global.getString(
72                     resolver, Settings.Global.NTP_SERVER);
73             final long timeout = Settings.Global.getLong(
74                     resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout);
75 
76             final String server = secureServer != null ? secureServer : defaultServer;
77             sSingleton = new NtpTrustedTime(server, timeout);
78             sContext = context;
79         }
80 
81         return sSingleton;
82     }
83 
84     @Override
85     @UnsupportedAppUsage
forceRefresh()86     public boolean forceRefresh() {
87         // We can't do this at initialization time: ConnectivityService might not be running yet.
88         synchronized (this) {
89             if (mCM == null) {
90                 mCM = sContext.getSystemService(ConnectivityManager.class);
91             }
92         }
93 
94         final Network network = mCM == null ? null : mCM.getActiveNetwork();
95         return forceRefresh(network);
96     }
97 
forceRefresh(Network network)98     public boolean forceRefresh(Network network) {
99         if (TextUtils.isEmpty(mServer)) {
100             // missing server, so no trusted time available
101             return false;
102         }
103 
104         // We can't do this at initialization time: ConnectivityService might not be running yet.
105         synchronized (this) {
106             if (mCM == null) {
107                 mCM = sContext.getSystemService(ConnectivityManager.class);
108             }
109         }
110 
111         final NetworkInfo ni = mCM == null ? null : mCM.getNetworkInfo(network);
112         if (ni == null || !ni.isConnected()) {
113             if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
114             return false;
115         }
116 
117 
118         if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
119         final SntpClient client = new SntpClient();
120         if (client.requestTime(mServer, (int) mTimeout, network)) {
121             mHasCache = true;
122             mCachedNtpTime = client.getNtpTime();
123             mCachedNtpElapsedRealtime = client.getNtpTimeReference();
124             mCachedNtpCertainty = client.getRoundTripTime() / 2;
125             return true;
126         } else {
127             return false;
128         }
129     }
130 
131     @Override
132     @UnsupportedAppUsage
hasCache()133     public boolean hasCache() {
134         return mHasCache;
135     }
136 
137     @Override
getCacheAge()138     public long getCacheAge() {
139         if (mHasCache) {
140             return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
141         } else {
142             return Long.MAX_VALUE;
143         }
144     }
145 
146     @Override
getCacheCertainty()147     public long getCacheCertainty() {
148         if (mHasCache) {
149             return mCachedNtpCertainty;
150         } else {
151             return Long.MAX_VALUE;
152         }
153     }
154 
155     @Override
156     @UnsupportedAppUsage
currentTimeMillis()157     public long currentTimeMillis() {
158         if (!mHasCache) {
159             throw new IllegalStateException("Missing authoritative time source");
160         }
161         if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
162 
163         // current time is age after the last ntp cache; callers who
164         // want fresh values will hit makeAuthoritative() first.
165         return mCachedNtpTime + getCacheAge();
166     }
167 
168     @UnsupportedAppUsage
getCachedNtpTime()169     public long getCachedNtpTime() {
170         if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
171         return mCachedNtpTime;
172     }
173 
174     @UnsupportedAppUsage
getCachedNtpTimeReference()175     public long getCachedNtpTimeReference() {
176         return mCachedNtpElapsedRealtime;
177     }
178 }
179