blob: ebcda44548f83e455bf0ab1f0966c7063a31543b [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;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080029import android.os.Binder;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070030import android.os.Handler;
Amith Yamasani450a16b2013-09-18 16:28:50 -070031import android.os.HandlerThread;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070032import android.os.Looper;
33import android.os.Message;
34import android.os.SystemClock;
Thierry Strudel8c842172015-10-29 14:40:29 -070035import android.os.PowerManager;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070036import android.provider.Settings;
37import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070038import android.util.NtpTrustedTime;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080039import android.util.TimeUtils;
Jeff Sharkey104344e2011-07-10 14:20:41 -070040import android.util.TrustedTime;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070041
Jeff Sharkey104344e2011-07-10 14:20:41 -070042import com.android.internal.telephony.TelephonyIntents;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060043import com.android.internal.util.DumpUtils;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070044
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080045import java.io.FileDescriptor;
46import java.io.PrintWriter;
47
Amith Yamasani6734b9f2010-09-13 16:24:08 -070048/**
49 * Monitors the network time and updates the system time if it is out of sync
50 * and there hasn't been any NITZ update from the carrier recently.
51 * If looking up the network time fails for some reason, it tries a few times with a short
52 * interval and then resets to checking on longer intervals.
53 * <p>
54 * If the user enables AUTO_TIME, it will check immediately for the network time, if NITZ wasn't
55 * available.
56 * </p>
57 */
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080058public class NetworkTimeUpdateService extends Binder {
Amith Yamasani6734b9f2010-09-13 16:24:08 -070059
60 private static final String TAG = "NetworkTimeUpdateService";
61 private static final boolean DBG = false;
62
63 private static final int EVENT_AUTO_TIME_CHANGED = 1;
64 private static final int EVENT_POLL_NETWORK_TIME = 2;
Lorenzo Colittidf590532015-01-22 22:35:33 +090065 private static final int EVENT_NETWORK_CHANGED = 3;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070066
Amith Yamasani6734b9f2010-09-13 16:24:08 -070067 private static final String ACTION_POLL =
68 "com.android.server.NetworkTimeUpdateService.action.POLL";
Fyodor Kupolov32af07a2016-02-26 16:54:25 -080069
70 private static final int NETWORK_CHANGE_EVENT_DELAY_MS = 1000;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070071 private static int POLL_REQUEST = 0;
72
73 private static final long NOT_SET = -1;
74 private long mNitzTimeSetTime = NOT_SET;
75 // TODO: Have a way to look up the timezone we are in
76 private long mNitzZoneSetTime = NOT_SET;
77
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;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070086 // The last time that we successfully fetched the NTP time.
87 private long mLastNtpFetchTime = NOT_SET;
Thierry Strudel8c842172015-10-29 14:40:29 -070088 private final PowerManager.WakeLock mWakeLock;
Jaewan Kimc3560b82012-11-20 23:58:07 +090089
90 // Normal polling frequency
91 private final long mPollingIntervalMs;
92 // Try-again polling interval, in case the network request failed
93 private final long mPollingIntervalShorterMs;
94 // Number of times to try again
95 private final int mTryAgainTimesMax;
96 // If the time difference is greater than this threshold, then update the time.
97 private final int mTimeErrorThresholdMs;
Amith Yamasani6734b9f2010-09-13 16:24:08 -070098 // Keeps track of how many quick attempts were made to fetch NTP time.
99 // During bootup, the network may not have been up yet, or it's taking time for the
100 // connection to happen.
101 private int mTryAgainCounter;
102
103 public NetworkTimeUpdateService(Context context) {
104 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700105 mTime = NtpTrustedTime.getInstance(context);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700106 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
107 Intent pollIntent = new Intent(ACTION_POLL, null);
108 mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
Jaewan Kimc3560b82012-11-20 23:58:07 +0900109
110 mPollingIntervalMs = mContext.getResources().getInteger(
111 com.android.internal.R.integer.config_ntpPollingInterval);
112 mPollingIntervalShorterMs = mContext.getResources().getInteger(
113 com.android.internal.R.integer.config_ntpPollingIntervalShorter);
114 mTryAgainTimesMax = mContext.getResources().getInteger(
115 com.android.internal.R.integer.config_ntpRetry);
116 mTimeErrorThresholdMs = mContext.getResources().getInteger(
117 com.android.internal.R.integer.config_ntpThreshold);
Thierry Strudel8c842172015-10-29 14:40:29 -0700118
119 mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
120 PowerManager.PARTIAL_WAKE_LOCK, TAG);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700121 }
122
123 /** Initialize the receivers and initiate the first NTP request */
Svetoslav Ganova0027152013-06-25 14:59:53 -0700124 public void systemRunning() {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700125 registerForTelephonyIntents();
126 registerForAlarms();
Amith Yamasani8d394fa2011-03-01 12:41:04 -0800127 registerForConnectivityIntents();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700128
Amith Yamasani450a16b2013-09-18 16:28:50 -0700129 HandlerThread thread = new HandlerThread(TAG);
130 thread.start();
131 mHandler = new MyHandler(thread.getLooper());
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700132 // Check the network time on the new thread
133 mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
134
135 mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
136 mSettingsObserver.observe(mContext);
137 }
138
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700139 private void registerForTelephonyIntents() {
140 IntentFilter intentFilter = new IntentFilter();
141 intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
142 intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
143 mContext.registerReceiver(mNitzReceiver, intentFilter);
144 }
145
146 private void registerForAlarms() {
147 mContext.registerReceiver(
148 new BroadcastReceiver() {
149 @Override
150 public void onReceive(Context context, Intent intent) {
151 mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
152 }
153 }, new IntentFilter(ACTION_POLL));
154 }
155
Amith Yamasani8d394fa2011-03-01 12:41:04 -0800156 private void registerForConnectivityIntents() {
157 IntentFilter intentFilter = new IntentFilter();
158 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
159 mContext.registerReceiver(mConnectivityReceiver, intentFilter);
160 }
161
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700162 private void onPollNetworkTime(int event) {
163 // If Automatic time is not set, don't bother.
164 if (!isAutomaticTimeRequested()) return;
Thierry Strudel8c842172015-10-29 14:40:29 -0700165 mWakeLock.acquire();
166 try {
167 onPollNetworkTimeUnderWakeLock(event);
168 } finally {
169 mWakeLock.release();
170 }
171 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700172
Thierry Strudel8c842172015-10-29 14:40:29 -0700173 private void onPollNetworkTimeUnderWakeLock(int event) {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700174 final long refTime = SystemClock.elapsedRealtime();
Jaewan Kimc3560b82012-11-20 23:58:07 +0900175 // If NITZ time was received less than mPollingIntervalMs time ago,
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700176 // no need to sync to NTP.
Jaewan Kimc3560b82012-11-20 23:58:07 +0900177 if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
178 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700179 return;
180 }
181 final long currentTime = System.currentTimeMillis();
182 if (DBG) Log.d(TAG, "System time = " + currentTime);
183 // Get the NTP time
Jaewan Kimc3560b82012-11-20 23:58:07 +0900184 if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700185 || event == EVENT_AUTO_TIME_CHANGED) {
186 if (DBG) Log.d(TAG, "Before Ntp fetch");
Jeff Sharkey104344e2011-07-10 14:20:41 -0700187
188 // force refresh NTP cache when outdated
Jaewan Kimc3560b82012-11-20 23:58:07 +0900189 if (mTime.getCacheAge() >= mPollingIntervalMs) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700190 mTime.forceRefresh();
191 }
192
193 // only update when NTP time is fresh
Jaewan Kimc3560b82012-11-20 23:58:07 +0900194 if (mTime.getCacheAge() < mPollingIntervalMs) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700195 final long ntp = mTime.currentTimeMillis();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700196 mTryAgainCounter = 0;
Amith Yamasani708d5d42012-05-02 11:50:31 -0700197 // If the clock is more than N seconds off or this is the first time it's been
198 // fetched since boot, set the current time.
Jaewan Kimc3560b82012-11-20 23:58:07 +0900199 if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
Amith Yamasani708d5d42012-05-02 11:50:31 -0700200 || mLastNtpFetchTime == NOT_SET) {
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700201 // Set the system time
Amith Yamasani708d5d42012-05-02 11:50:31 -0700202 if (DBG && mLastNtpFetchTime == NOT_SET
Jaewan Kimc3560b82012-11-20 23:58:07 +0900203 && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) {
Amith Yamasani708d5d42012-05-02 11:50:31 -0700204 Log.d(TAG, "For initial setup, rtc = " + currentTime);
205 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700206 if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp);
207 // Make sure we don't overflow, since it's going to be converted to an int
208 if (ntp / 1000 < Integer.MAX_VALUE) {
209 SystemClock.setCurrentTimeMillis(ntp);
210 }
211 } else {
212 if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp);
213 }
Amith Yamasani708d5d42012-05-02 11:50:31 -0700214 mLastNtpFetchTime = SystemClock.elapsedRealtime();
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700215 } else {
216 // Try again shortly
217 mTryAgainCounter++;
Jaewan Kimc3560b82012-11-20 23:58:07 +0900218 if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
219 resetAlarm(mPollingIntervalShorterMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700220 } else {
221 // Try much later
222 mTryAgainCounter = 0;
Jaewan Kimc3560b82012-11-20 23:58:07 +0900223 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700224 }
225 return;
226 }
227 }
Jaewan Kimc3560b82012-11-20 23:58:07 +0900228 resetAlarm(mPollingIntervalMs);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700229 }
230
231 /**
232 * Cancel old alarm and starts a new one for the specified interval.
233 *
234 * @param interval when to trigger the alarm, starting from now.
235 */
236 private void resetAlarm(long interval) {
237 mAlarmManager.cancel(mPendingPollIntent);
238 long now = SystemClock.elapsedRealtime();
239 long next = now + interval;
240 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
241 }
242
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700243 /**
244 * Checks if the user prefers to automatically set the time.
245 */
246 private boolean isAutomaticTimeRequested() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700247 return Settings.Global.getInt(
248 mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0) != 0;
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700249 }
250
251 /** Receiver for Nitz time events */
252 private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() {
253
254 @Override
255 public void onReceive(Context context, Intent intent) {
256 String action = intent.getAction();
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800257 if (DBG) Log.d(TAG, "Received " + action);
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700258 if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
259 mNitzTimeSetTime = SystemClock.elapsedRealtime();
260 } else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) {
261 mNitzZoneSetTime = SystemClock.elapsedRealtime();
262 }
263 }
264 };
265
Amith Yamasani8d394fa2011-03-01 12:41:04 -0800266 /** Receiver for ConnectivityManager events */
267 private BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
268
269 @Override
270 public void onReceive(Context context, Intent intent) {
271 String action = intent.getAction();
272 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800273 if (DBG) Log.d(TAG, "Received CONNECTIVITY_ACTION ");
Lorenzo Colittidf590532015-01-22 22:35:33 +0900274 // Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800275 Message message = mHandler.obtainMessage(EVENT_NETWORK_CHANGED);
276 // Send with a short delay to make sure the network is ready for use
277 mHandler.sendMessageDelayed(message, NETWORK_CHANGE_EVENT_DELAY_MS);
Amith Yamasani8d394fa2011-03-01 12:41:04 -0800278 }
279 }
280 };
281
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700282 /** Handler to do the network accesses on */
283 private class MyHandler extends Handler {
284
285 public MyHandler(Looper l) {
286 super(l);
287 }
288
289 @Override
290 public void handleMessage(Message msg) {
291 switch (msg.what) {
292 case EVENT_AUTO_TIME_CHANGED:
293 case EVENT_POLL_NETWORK_TIME:
Lorenzo Colittidf590532015-01-22 22:35:33 +0900294 case EVENT_NETWORK_CHANGED:
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700295 onPollNetworkTime(msg.what);
296 break;
297 }
298 }
299 }
300
301 /** Observer to watch for changes to the AUTO_TIME setting */
302 private static class SettingsObserver extends ContentObserver {
303
304 private int mMsg;
305 private Handler mHandler;
306
307 SettingsObserver(Handler handler, int msg) {
308 super(handler);
309 mHandler = handler;
310 mMsg = msg;
311 }
312
313 void observe(Context context) {
314 ContentResolver resolver = context.getContentResolver();
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700315 resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700316 false, this);
317 }
318
319 @Override
320 public void onChange(boolean selfChange) {
321 mHandler.obtainMessage(mMsg).sendToTarget();
322 }
323 }
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800324
325 @Override
326 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600327 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Fyodor Kupolov32af07a2016-02-26 16:54:25 -0800328 pw.print("PollingIntervalMs: ");
329 TimeUtils.formatDuration(mPollingIntervalMs, pw);
330 pw.print("\nPollingIntervalShorterMs: ");
331 TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
332 pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
333 pw.print("TimeErrorThresholdMs: ");
334 TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
335 pw.println("\nTryAgainCounter: " + mTryAgainCounter);
336 pw.print("LastNtpFetchTime: ");
337 TimeUtils.formatDuration(mLastNtpFetchTime, pw);
338 pw.println();
339 }
Amith Yamasani6734b9f2010-09-13 16:24:08 -0700340}