Home | History | Annotate | Download | only in util
      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 
     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 
     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.Secure.getString(
     63                     resolver, Settings.Secure.NTP_SERVER);
     64             final long timeout = Settings.Secure.getLong(
     65                     resolver, Settings.Secure.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     /** {@inheritDoc} */
     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     /** {@inheritDoc} */
     95     public boolean hasCache() {
     96         return mHasCache;
     97     }
     98 
     99     /** {@inheritDoc} */
    100     public long getCacheAge() {
    101         if (mHasCache) {
    102             return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
    103         } else {
    104             return Long.MAX_VALUE;
    105         }
    106     }
    107 
    108     /** {@inheritDoc} */
    109     public long getCacheCertainty() {
    110         if (mHasCache) {
    111             return mCachedNtpCertainty;
    112         } else {
    113             return Long.MAX_VALUE;
    114         }
    115     }
    116 
    117     /** {@inheritDoc} */
    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 
    129     public long getCachedNtpTime() {
    130         if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
    131         return mCachedNtpTime;
    132     }
    133 
    134     public long getCachedNtpTimeReference() {
    135         return mCachedNtpElapsedRealtime;
    136     }
    137 }
    138