blob: 7894788cb0b633b14e3e08299961bad1ec9d86ea [file] [log] [blame]
Neil Fullerb3d6abb2018-06-21 15:16:36 +01001/*
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
19import android.app.AlarmManager;
20import android.app.PendingIntent;
Neil Fuller4ab8a192019-12-16 16:54:06 +000021import android.app.timedetector.NetworkTimeSuggestion;
22import android.app.timedetector.TimeDetector;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010023import android.content.BroadcastReceiver;
24import android.content.ContentResolver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010028import android.database.ContentObserver;
29import android.net.ConnectivityManager;
30import android.net.ConnectivityManager.NetworkCallback;
31import android.net.Network;
32import android.os.Binder;
33import android.os.Handler;
34import android.os.HandlerThread;
35import android.os.Looper;
36import android.os.Message;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010037import android.os.PowerManager;
Neil Fullerca48eb72018-06-27 11:40:06 +010038import android.os.SystemClock;
Neil Fullerd1590152020-01-08 16:31:44 +000039import android.os.TimestampedValue;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010040import android.provider.Settings;
41import android.util.Log;
42import android.util.NtpTrustedTime;
43import android.util.TimeUtils;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010044
Neil Fullerb3d6abb2018-06-21 15:16:36 +010045import com.android.internal.util.DumpUtils;
46
47import java.io.FileDescriptor;
48import java.io.PrintWriter;
49
50/**
Neil Fuller4ab8a192019-12-16 16:54:06 +000051 * Monitors the network time. If looking up the network time fails for some reason, it tries a few
52 * times with a short interval and then resets to checking on longer intervals.
53 *
54 * <p>When available, the time is always suggested to the {@link
55 * com.android.server.timedetector.TimeDetectorService} where it may be used to set the device
56 * system clock, depending on user settings and what other signals are available.
Neil Fullerb3d6abb2018-06-21 15:16:36 +010057 */
Neil Fullere9efed92019-06-27 15:01:01 +010058public class NetworkTimeUpdateServiceImpl extends Binder implements NetworkTimeUpdateService {
Neil Fullerb3d6abb2018-06-21 15:16:36 +010059
60 private static final String TAG = "NetworkTimeUpdateService";
61 private static final boolean DBG = false;
62
Neil Fuller4ab8a192019-12-16 16:54:06 +000063 private static final int EVENT_AUTO_TIME_ENABLED = 1;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010064 private static final int EVENT_POLL_NETWORK_TIME = 2;
65 private static final int EVENT_NETWORK_CHANGED = 3;
66
67 private static final String ACTION_POLL =
68 "com.android.server.NetworkTimeUpdateService.action.POLL";
69
70 private static final int POLL_REQUEST = 0;
71
Neil Fullerb3d6abb2018-06-21 15:16:36 +010072 private Network mDefaultNetwork = null;
73
Neil Fullerca48eb72018-06-27 11:40:06 +010074 private final Context mContext;
75 private final NtpTrustedTime mTime;
76 private final AlarmManager mAlarmManager;
Neil Fuller4ab8a192019-12-16 16:54:06 +000077 private final TimeDetector mTimeDetector;
Neil Fullerca48eb72018-06-27 11:40:06 +010078 private final ConnectivityManager mCM;
79 private final PendingIntent mPendingPollIntent;
80 private final PowerManager.WakeLock mWakeLock;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010081
82 // NTP lookup is done on this thread and handler
83 private Handler mHandler;
Neil Fuller4ab8a192019-12-16 16:54:06 +000084 private AutoTimeSettingObserver mAutoTimeSettingObserver;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010085 private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010086
87 // Normal polling frequency
88 private final long mPollingIntervalMs;
89 // Try-again polling interval, in case the network request failed
90 private final long mPollingIntervalShorterMs;
91 // Number of times to try again
92 private final int mTryAgainTimesMax;
Neil Fullerb3d6abb2018-06-21 15:16:36 +010093 // Keeps track of how many quick attempts were made to fetch NTP time.
94 // During bootup, the network may not have been up yet, or it's taking time for the
95 // connection to happen.
96 private int mTryAgainCounter;
97
Neil Fullere9efed92019-06-27 15:01:01 +010098 public NetworkTimeUpdateServiceImpl(Context context) {
Neil Fullerb3d6abb2018-06-21 15:16:36 +010099 mContext = context;
100 mTime = NtpTrustedTime.getInstance(context);
Neil Fullerca48eb72018-06-27 11:40:06 +0100101 mAlarmManager = mContext.getSystemService(AlarmManager.class);
Neil Fuller4ab8a192019-12-16 16:54:06 +0000102 mTimeDetector = mContext.getSystemService(TimeDetector.class);
Neil Fullerca48eb72018-06-27 11:40:06 +0100103 mCM = mContext.getSystemService(ConnectivityManager.class);
104
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100105 Intent pollIntent = new Intent(ACTION_POLL, null);
106 mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
107
108 mPollingIntervalMs = mContext.getResources().getInteger(
109 com.android.internal.R.integer.config_ntpPollingInterval);
110 mPollingIntervalShorterMs = mContext.getResources().getInteger(
111 com.android.internal.R.integer.config_ntpPollingIntervalShorter);
112 mTryAgainTimesMax = mContext.getResources().getInteger(
113 com.android.internal.R.integer.config_ntpRetry);
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100114
Neil Fullerca48eb72018-06-27 11:40:06 +0100115 mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100116 PowerManager.PARTIAL_WAKE_LOCK, TAG);
117 }
118
Neil Fullerca48eb72018-06-27 11:40:06 +0100119 @Override
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100120 public void systemRunning() {
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100121 registerForAlarms();
122
123 HandlerThread thread = new HandlerThread(TAG);
124 thread.start();
125 mHandler = new MyHandler(thread.getLooper());
126 mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
127 mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
128
Neil Fuller4ab8a192019-12-16 16:54:06 +0000129 mAutoTimeSettingObserver = new AutoTimeSettingObserver(mContext, mHandler,
130 EVENT_AUTO_TIME_ENABLED);
131 mAutoTimeSettingObserver.observe();
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100132 }
133
134 private void registerForAlarms() {
135 mContext.registerReceiver(
136 new BroadcastReceiver() {
137 @Override
138 public void onReceive(Context context, Intent intent) {
139 mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
140 }
141 }, new IntentFilter(ACTION_POLL));
142 }
143
144 private void onPollNetworkTime(int event) {
Neil Fuller4ab8a192019-12-16 16:54:06 +0000145 // If we don't have any default network, don't bother.
Neil Fullerca48eb72018-06-27 11:40:06 +0100146 if (mDefaultNetwork == null) return;
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100147 mWakeLock.acquire();
148 try {
149 onPollNetworkTimeUnderWakeLock(event);
150 } finally {
151 mWakeLock.release();
152 }
153 }
154
155 private void onPollNetworkTimeUnderWakeLock(int event) {
Neil Fullerca48eb72018-06-27 11:40:06 +0100156 // Force an NTP fix when outdated
Neil Fuller65f0f312019-12-20 15:59:38 +0000157 NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult();
158 if (cachedNtpResult == null || cachedNtpResult.getAgeMillis() >= mPollingIntervalMs) {
Neil Fullerca48eb72018-06-27 11:40:06 +0100159 if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
160 mTime.forceRefresh();
Neil Fuller65f0f312019-12-20 15:59:38 +0000161 cachedNtpResult = mTime.getCachedTimeResult();
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100162 }
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100163
Neil Fuller65f0f312019-12-20 15:59:38 +0000164 if (cachedNtpResult != null && cachedNtpResult.getAgeMillis() < mPollingIntervalMs) {
Neil Fullerca48eb72018-06-27 11:40:06 +0100165 // Obtained fresh fix; schedule next normal update
166 resetAlarm(mPollingIntervalMs);
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100167
Neil Fuller4ab8a192019-12-16 16:54:06 +0000168 // Suggest the time to the time detector. It may choose use it to set the system clock.
Neil Fuller65f0f312019-12-20 15:59:38 +0000169 TimestampedValue<Long> timeSignal = new TimestampedValue<>(
170 cachedNtpResult.getElapsedRealtimeMillis(), cachedNtpResult.getTimeMillis());
Neil Fuller4ab8a192019-12-16 16:54:06 +0000171 NetworkTimeSuggestion timeSuggestion = new NetworkTimeSuggestion(timeSignal);
172 timeSuggestion.addDebugInfo("Origin: NetworkTimeUpdateServiceImpl. event=" + event);
173 mTimeDetector.suggestNetworkTime(timeSuggestion);
Neil Fullerca48eb72018-06-27 11:40:06 +0100174 } else {
175 // No fresh fix; schedule retry
176 mTryAgainCounter++;
177 if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
178 resetAlarm(mPollingIntervalShorterMs);
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100179 } else {
Neil Fullerca48eb72018-06-27 11:40:06 +0100180 // Try much later
181 mTryAgainCounter = 0;
182 resetAlarm(mPollingIntervalMs);
183 }
184 }
185 }
186
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100187 /**
188 * Cancel old alarm and starts a new one for the specified interval.
189 *
190 * @param interval when to trigger the alarm, starting from now.
191 */
192 private void resetAlarm(long interval) {
193 mAlarmManager.cancel(mPendingPollIntent);
194 long now = SystemClock.elapsedRealtime();
195 long next = now + interval;
196 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
197 }
198
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100199 /** Handler to do the network accesses on */
200 private class MyHandler extends Handler {
201
202 public MyHandler(Looper l) {
203 super(l);
204 }
205
206 @Override
207 public void handleMessage(Message msg) {
208 switch (msg.what) {
Neil Fuller4ab8a192019-12-16 16:54:06 +0000209 case EVENT_AUTO_TIME_ENABLED:
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100210 case EVENT_POLL_NETWORK_TIME:
211 case EVENT_NETWORK_CHANGED:
212 onPollNetworkTime(msg.what);
213 break;
214 }
215 }
216 }
217
218 private class NetworkTimeUpdateCallback extends NetworkCallback {
219 @Override
220 public void onAvailable(Network network) {
221 Log.d(TAG, String.format("New default network %s; checking time.", network));
222 mDefaultNetwork = network;
223 // Running on mHandler so invoke directly.
224 onPollNetworkTime(EVENT_NETWORK_CHANGED);
225 }
226
227 @Override
228 public void onLost(Network network) {
229 if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
230 }
231 }
232
Neil Fuller4ab8a192019-12-16 16:54:06 +0000233 /**
234 * Observer to watch for changes to the AUTO_TIME setting. It only triggers when the setting
235 * is enabled.
236 */
237 private static class AutoTimeSettingObserver extends ContentObserver {
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100238
Neil Fuller4ab8a192019-12-16 16:54:06 +0000239 private final Context mContext;
240 private final int mMsg;
241 private final Handler mHandler;
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100242
Neil Fuller4ab8a192019-12-16 16:54:06 +0000243 AutoTimeSettingObserver(Context context, Handler handler, int msg) {
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100244 super(handler);
Neil Fuller4ab8a192019-12-16 16:54:06 +0000245 mContext = context;
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100246 mHandler = handler;
247 mMsg = msg;
248 }
249
Neil Fuller4ab8a192019-12-16 16:54:06 +0000250 void observe() {
251 ContentResolver resolver = mContext.getContentResolver();
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100252 resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
253 false, this);
254 }
255
256 @Override
257 public void onChange(boolean selfChange) {
Neil Fuller4ab8a192019-12-16 16:54:06 +0000258 if (isAutomaticTimeEnabled()) {
259 mHandler.obtainMessage(mMsg).sendToTarget();
260 }
261 }
262
263 /**
264 * Checks if the user prefers to automatically set the time.
265 */
266 private boolean isAutomaticTimeEnabled() {
267 ContentResolver resolver = mContext.getContentResolver();
268 return Settings.Global.getInt(resolver, Settings.Global.AUTO_TIME, 0) != 0;
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100269 }
270 }
271
272 @Override
273 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
274 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
275 pw.print("PollingIntervalMs: ");
276 TimeUtils.formatDuration(mPollingIntervalMs, pw);
277 pw.print("\nPollingIntervalShorterMs: ");
278 TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
279 pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100280 pw.println("\nTryAgainCounter: " + mTryAgainCounter);
Neil Fuller65f0f312019-12-20 15:59:38 +0000281 NtpTrustedTime.TimeResult ntpResult = mTime.getCachedTimeResult();
282 pw.println("NTP cache result: " + ntpResult);
283 if (ntpResult != null) {
284 pw.println("NTP result age: " + ntpResult.getAgeMillis());
285 }
Neil Fullerb3d6abb2018-06-21 15:16:36 +0100286 pw.println();
287 }
288}