blob: 2c24798204eb02fd375a8e3d3d7ec5c19f09de3f [file] [log] [blame]
Amith Yamasani6734b9f2010-09-13 16:24:08 -07001/*
2 * Copyright (C) 2010 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
17package com.android.server;
18
Amith Yamasani6734b9f2010-09-13 16:24:08 -070019import android.app.AlarmManager;
20import android.app.PendingIntent;
21import android.content.BroadcastReceiver;
22import android.content.ContentResolver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080026import android.content.pm.PackageManager;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070027import android.database.ContentObserver;
Amith Yamasani8d394fa2011-03-01 12:41:04 -080028import android.net.ConnectivityManager;
zhoulei45d1b262017-05-10 18:09:50 +080029import android.net.ConnectivityManager.NetworkCallback;
30import android.net.Network;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080031import android.os.Binder;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070032import android.os.Handler;
Amith Yamasani450a16b2013-09-18 16:28:50 -070033import android.os.HandlerThread;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070034import android.os.Looper;
35import android.os.Message;
36import android.os.SystemClock;
Thierry Strudel8c842172015-10-29 14:40:29 -070037import android.os.PowerManager;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070038import android.provider.Settings;
39import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070040import android.util.NtpTrustedTime;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080041import android.util.TimeUtils;
Jeff Sharkey104344e2011-07-10 14:20:41 -070042import android.util.TrustedTime;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070043
Jeff Sharkey104344e2011-07-10 14:20:41 -070044import com.android.internal.telephony.TelephonyIntents;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060045import com.android.internal.util.DumpUtils;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070046
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080047import java.io.FileDescriptor;
48import java.io.PrintWriter;
49
Amith Yamasani6734b9f2010-09-13 16:24:08 -070050/**
51 * Monitors the network time and updates the system time if it is out of sync
52 * and there hasn't been any NITZ update from the carrier recently.
53 * If looking up the network time fails for some reason, it tries a few times with a short
54 * interval and then resets to checking on longer intervals.
55 * <p>
56 * If the user enables AUTO_TIME, it will check immediately for the network time, if NITZ wasn't
57 * available.
58 * </p>
59 */
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080060public class NetworkTimeUpdateService extends Binder {
Amith Yamasani6734b9f2010-09-13 16:24:08 -070061
62 private static final String TAG = "NetworkTimeUpdateService";
63 private static final boolean DBG = false;
64
65 private static final int EVENT_AUTO_TIME_CHANGED = 1;
66 private static final int EVENT_POLL_NETWORK_TIME = 2;
Lorenzo Colittidf590532015-01-22 22:35:33 +090067 private static final int EVENT_NETWORK_CHANGED = 3;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070068
Amith Yamasani6734b9f2010-09-13 16:24:08 -070069 private static final String ACTION_POLL =
70 "com.android.server.NetworkTimeUpdateService.action.POLL";
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080071
Neil Fullerc1211b52017-11-24 08:51:40 +000072 private static final int POLL_REQUEST = 0;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070073
74 private static final long NOT_SET = -1;
75 private long mNitzTimeSetTime = NOT_SET;
zhoulei45d1b262017-05-10 18:09:50 +080076 private Network mDefaultNetwork = null;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070077
78 private Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -070079 private TrustedTime mTime;
80
Amith Yamasani6734b9f2010-09-13 16:24:08 -070081 // NTP lookup is done on this thread and handler
82 private Handler mHandler;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070083 private AlarmManager mAlarmManager;
84 private PendingIntent mPendingPollIntent;
85 private SettingsObserver mSettingsObserver;
zhoulei45d1b262017-05-10 18:09:50 +080086 private ConnectivityManager mCM;
87 private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070088 // The last time that we successfully fetched the NTP time.
89 private long mLastNtpFetchTime = NOT_SET;
Thierry Strudel8c842172015-10-29 14:40:29 -070090 private final PowerManager.WakeLock mWakeLock;
Jaewan Kimc3560b82012-11-20 23:58:07 +090091
92 // Normal polling frequency
93 private final long mPollingIntervalMs;
94 // Try-again polling interval, in case the network request failed
95 private final long mPollingIntervalShorterMs;
96 // Number of times to try again
97 private final int mTryAgainTimesMax;
98 // If the time difference is greater than this threshold, then update the time.
99 private final int mTimeErrorThresholdMs;
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700100 // Keeps track of how many quick attempts were made to fetch NTP time.
101 // During bootup, the network may not have been up yet, or it's taking time for the
102 // connection to happen.
103 private int mTryAgainCounter;
104
105 public NetworkTimeUpdateService(Context context) {
106 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700107 mTime = NtpTrustedTime.getInstance(context);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700108 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
zhoulei45d1b262017-05-10 18:09:50 +0800109 mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700110 Intent pollIntent = new Intent(ACTION_POLL, null);
111 mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
Jaewan Kimc3560b82012-11-20 23:58:07 +0900112
113 mPollingIntervalMs = mContext.getResources().getInteger(
114 com.android.internal.R.integer.config_ntpPollingInterval);
115 mPollingIntervalShorterMs = mContext.getResources().getInteger(
116 com.android.internal.R.integer.config_ntpPollingIntervalShorter);
117 mTryAgainTimesMax = mContext.getResources().getInteger(
118 com.android.internal.R.integer.config_ntpRetry);
119 mTimeErrorThresholdMs = mContext.getResources().getInteger(
120 com.android.internal.R.integer.config_ntpThreshold);
Thierry Strudel8c842172015-10-29 14:40:29 -0700121
122 mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
123 PowerManager.PARTIAL_WAKE_LOCK, TAG);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700124 }
125
126 /** Initialize the receivers and initiate the first NTP request */
Svetoslav Ganova0027152013-06-25 14:59:53 -0700127 public void systemRunning() {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700128 registerForTelephonyIntents();
129 registerForAlarms();
130
Amith Yamasani450a16b2013-09-18 16:28:50 -0700131 HandlerThread thread = new HandlerThread(TAG);
132 thread.start();
133 mHandler = new MyHandler(thread.getLooper());
zhoulei45d1b262017-05-10 18:09:50 +0800134 mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
135 mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700136
137 mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
138 mSettingsObserver.observe(mContext);
139 }
140
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700141 private void registerForTelephonyIntents() {
142 IntentFilter intentFilter = new IntentFilter();
143 intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700144 mContext.registerReceiver(mNitzReceiver, intentFilter);
145 }
146
147 private void registerForAlarms() {
148 mContext.registerReceiver(
149 new BroadcastReceiver() {
150 @Override
151 public void onReceive(Context context, Intent intent) {
152 mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
153 }
154 }, new IntentFilter(ACTION_POLL));
155 }
156
157 private void onPollNetworkTime(int event) {
zhoulei45d1b262017-05-10 18:09:50 +0800158 // If Automatic time is not set, don't bother. Similarly, if we don't
159 // have any default network, don't bother.
160 if (!isAutomaticTimeRequested() || mDefaultNetwork == null) return;
Thierry Strudel8c842172015-10-29 14:40:29 -0700161 mWakeLock.acquire();
162 try {
163 onPollNetworkTimeUnderWakeLock(event);
164 } finally {
165 mWakeLock.release();
166 }
167 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700168
Thierry Strudel8c842172015-10-29 14:40:29 -0700169 private void onPollNetworkTimeUnderWakeLock(int event) {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700170 final long refTime = SystemClock.elapsedRealtime();
Jaewan Kimc3560b82012-11-20 23:58:07 +0900171 // If NITZ time was received less than mPollingIntervalMs time ago,
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700172 // no need to sync to NTP.
Jaewan Kimc3560b82012-11-20 23:58:07 +0900173 if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
174 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700175 return;
176 }
177 final long currentTime = System.currentTimeMillis();
178 if (DBG) Log.d(TAG, "System time = " + currentTime);
179 // Get the NTP time
Jaewan Kimc3560b82012-11-20 23:58:07 +0900180 if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700181 || event == EVENT_AUTO_TIME_CHANGED) {
182 if (DBG) Log.d(TAG, "Before Ntp fetch");
Jeff Sharkey104344e2011-07-10 14:20:41 -0700183
184 // force refresh NTP cache when outdated
Jaewan Kimc3560b82012-11-20 23:58:07 +0900185 if (mTime.getCacheAge() >= mPollingIntervalMs) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700186 mTime.forceRefresh();
187 }
188
189 // only update when NTP time is fresh
Jaewan Kimc3560b82012-11-20 23:58:07 +0900190 if (mTime.getCacheAge() < mPollingIntervalMs) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700191 final long ntp = mTime.currentTimeMillis();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700192 mTryAgainCounter = 0;
Amith Yamasani708d5d42012-05-02 11:50:31 -0700193 // If the clock is more than N seconds off or this is the first time it's been
194 // fetched since boot, set the current time.
Jaewan Kimc3560b82012-11-20 23:58:07 +0900195 if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
Amith Yamasani708d5d42012-05-02 11:50:31 -0700196 || mLastNtpFetchTime == NOT_SET) {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700197 // Set the system time
Amith Yamasani708d5d42012-05-02 11:50:31 -0700198 if (DBG && mLastNtpFetchTime == NOT_SET
Jaewan Kimc3560b82012-11-20 23:58:07 +0900199 && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) {
Amith Yamasani708d5d42012-05-02 11:50:31 -0700200 Log.d(TAG, "For initial setup, rtc = " + currentTime);
201 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700202 if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp);
203 // Make sure we don't overflow, since it's going to be converted to an int
204 if (ntp / 1000 < Integer.MAX_VALUE) {
205 SystemClock.setCurrentTimeMillis(ntp);
206 }
207 } else {
208 if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp);
209 }
Amith Yamasani708d5d42012-05-02 11:50:31 -0700210 mLastNtpFetchTime = SystemClock.elapsedRealtime();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700211 } else {
212 // Try again shortly
213 mTryAgainCounter++;
Jaewan Kimc3560b82012-11-20 23:58:07 +0900214 if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
215 resetAlarm(mPollingIntervalShorterMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700216 } else {
217 // Try much later
218 mTryAgainCounter = 0;
Jaewan Kimc3560b82012-11-20 23:58:07 +0900219 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700220 }
221 return;
222 }
223 }
Jaewan Kimc3560b82012-11-20 23:58:07 +0900224 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700225 }
226
227 /**
228 * Cancel old alarm and starts a new one for the specified interval.
229 *
230 * @param interval when to trigger the alarm, starting from now.
231 */
232 private void resetAlarm(long interval) {
233 mAlarmManager.cancel(mPendingPollIntent);
234 long now = SystemClock.elapsedRealtime();
235 long next = now + interval;
236 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
237 }
238
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700239 /**
240 * Checks if the user prefers to automatically set the time.
241 */
242 private boolean isAutomaticTimeRequested() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700243 return Settings.Global.getInt(
244 mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0) != 0;
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700245 }
246
247 /** Receiver for Nitz time events */
248 private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() {
249
250 @Override
251 public void onReceive(Context context, Intent intent) {
252 String action = intent.getAction();
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800253 if (DBG) Log.d(TAG, "Received " + action);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700254 if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
255 mNitzTimeSetTime = SystemClock.elapsedRealtime();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700256 }
257 }
258 };
259
260 /** Handler to do the network accesses on */
261 private class MyHandler extends Handler {
262
263 public MyHandler(Looper l) {
264 super(l);
265 }
266
267 @Override
268 public void handleMessage(Message msg) {
269 switch (msg.what) {
270 case EVENT_AUTO_TIME_CHANGED:
271 case EVENT_POLL_NETWORK_TIME:
Lorenzo Colittidf590532015-01-22 22:35:33 +0900272 case EVENT_NETWORK_CHANGED:
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700273 onPollNetworkTime(msg.what);
274 break;
275 }
276 }
277 }
278
zhoulei45d1b262017-05-10 18:09:50 +0800279 private class NetworkTimeUpdateCallback extends NetworkCallback {
280 @Override
281 public void onAvailable(Network network) {
282 Log.d(TAG, String.format("New default network %s; checking time.", network));
283 mDefaultNetwork = network;
284 // Running on mHandler so invoke directly.
285 onPollNetworkTime(EVENT_NETWORK_CHANGED);
286 }
287
288 @Override
289 public void onLost(Network network) {
290 if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
291 }
292 }
293
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700294 /** Observer to watch for changes to the AUTO_TIME setting */
295 private static class SettingsObserver extends ContentObserver {
296
297 private int mMsg;
298 private Handler mHandler;
299
300 SettingsObserver(Handler handler, int msg) {
301 super(handler);
302 mHandler = handler;
303 mMsg = msg;
304 }
305
306 void observe(Context context) {
307 ContentResolver resolver = context.getContentResolver();
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700308 resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700309 false, this);
310 }
311
312 @Override
313 public void onChange(boolean selfChange) {
314 mHandler.obtainMessage(mMsg).sendToTarget();
315 }
316 }
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800317
318 @Override
319 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600320 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800321 pw.print("PollingIntervalMs: ");
322 TimeUtils.formatDuration(mPollingIntervalMs, pw);
323 pw.print("\nPollingIntervalShorterMs: ");
324 TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
325 pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
326 pw.print("TimeErrorThresholdMs: ");
327 TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
328 pw.println("\nTryAgainCounter: " + mTryAgainCounter);
329 pw.print("LastNtpFetchTime: ");
330 TimeUtils.formatDuration(mLastNtpFetchTime, pw);
331 pw.println();
332 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700333}