NtpTrustedTime.java revision b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7c
1b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey/*
2b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey *
4b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * you may not use this file except in compliance with the License.
6b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * You may obtain a copy of the License at
7b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey *
8b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey *
10b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * See the License for the specific language governing permissions and
14b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * limitations under the License.
15b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey */
16b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
17b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeypackage android.util;
18b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
19b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport android.net.SntpClient;
20b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport android.os.SystemClock;
21b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
22b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey/**
23b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * {@link TrustedTime} that connects with a remote NTP server as its remote
24b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * trusted time source.
25b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey *
26b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey * @hide
27b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey */
28b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeypublic class NtpTrustedTime implements TrustedTime {
29b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private String mNtpServer;
30b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private long mNtpTimeout;
31b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
32b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private boolean mHasCache;
33b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private long mCachedNtpTime;
34b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private long mCachedNtpElapsedRealtime;
35b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private long mCachedNtpCertainty;
36b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
37b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public NtpTrustedTime() {
38b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
39b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
40b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public void setNtpServer(String server, long timeout) {
41b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mNtpServer = server;
42b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mNtpTimeout = timeout;
43b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
44b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
45b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    /** {@inheritDoc} */
46b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public boolean forceRefresh() {
47b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mNtpServer == null) {
48b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            throw new IllegalStateException("Missing NTP server");
49b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
50b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
51b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        final SntpClient client = new SntpClient();
52b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (client.requestTime(mNtpServer, (int) mNtpTimeout)) {
53b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mHasCache = true;
54b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mCachedNtpTime = client.getNtpTime();
55b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mCachedNtpElapsedRealtime = client.getNtpTimeReference();
56b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mCachedNtpCertainty = client.getRoundTripTime() / 2;
57b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return true;
58b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        } else {
59b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return false;
60b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
61b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
62b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
63b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    /** {@inheritDoc} */
64b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public boolean hasCache() {
65b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        return mHasCache;
66b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
67b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
68b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    /** {@inheritDoc} */
69b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public long getCacheAge() {
70b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mHasCache) {
71b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
72b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        } else {
73b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return Long.MAX_VALUE;
74b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
75b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
76b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
77b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    /** {@inheritDoc} */
78b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public long getCacheCertainty() {
79b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mHasCache) {
80b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return mCachedNtpCertainty;
81b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        } else {
82b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            return Long.MAX_VALUE;
83b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
84b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
85b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
86b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    /** {@inheritDoc} */
87b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public long currentTimeMillis() {
88b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (!mHasCache) {
89b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            throw new IllegalStateException("Missing authoritative time source");
90b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
91b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
92b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        // current time is age after the last ntp cache; callers who
93b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        // want fresh values will hit makeAuthoritative() first.
94b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        return mCachedNtpTime + getCacheAge();
95b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
96b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey}
97