From 104344e507610be42fb70c7deda3c422c543bfcb Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sun, 10 Jul 2011 14:20:41 -0700 Subject: Cached NTP time for system services. Uses NTP server and timeout from secure settings, or fallback to defaults in resources. Update various system services to use cached NTP time when fresh enough, or force updates as needed. Bug: 4517273 Change-Id: Ie1c4c4883836013d02ca0bbd850cf8949f93b34b --- core/java/android/provider/Settings.java | 5 ++ core/java/android/util/NtpTrustedTime.java | 60 +++++++++++++++---- core/res/res/values/config.xml | 5 ++ .../android/server/NetworkTimeUpdateService.java | 67 +++++----------------- .../java/com/android/server/ThrottleService.java | 33 ++--------- .../server/location/GpsLocationProvider.java | 31 +++++----- .../server/net/NetworkPolicyManagerService.java | 3 +- .../android/server/net/NetworkStatsService.java | 7 +-- 8 files changed, 98 insertions(+), 113 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 65babc2dea9b..23b53ae04ba4 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3833,6 +3833,11 @@ public final class Settings { /** {@hide} */ public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history"; + /** Preferred NTP server. {@hide} */ + public static final String NTP_SERVER = "ntp_server"; + /** Timeout in milliseconds to wait for NTP server. {@hide} */ + public static final String NTP_TIMEOUT = "ntp_timeout"; + /** * @hide */ diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 5b19ecdb8b8a..2179ff36e1c7 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -16,41 +16,71 @@ package android.util; +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; import android.net.SntpClient; import android.os.SystemClock; +import android.provider.Settings; /** - * {@link TrustedTime} that connects with a remote NTP server as its remote - * trusted time source. + * {@link TrustedTime} that connects with a remote NTP server as its trusted + * time source. * * @hide */ public class NtpTrustedTime implements TrustedTime { - private String mNtpServer; - private long mNtpTimeout; + private static final String TAG = "NtpTrustedTime"; + private static final boolean LOGD = false; + + private static NtpTrustedTime sSingleton; + + private final String mServer; + private final long mTimeout; private boolean mHasCache; private long mCachedNtpTime; private long mCachedNtpElapsedRealtime; private long mCachedNtpCertainty; - public NtpTrustedTime() { + private NtpTrustedTime(String server, long timeout) { + if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server); + mServer = server; + mTimeout = timeout; } - public void setNtpServer(String server, long timeout) { - mNtpServer = server; - mNtpTimeout = timeout; + public static synchronized NtpTrustedTime getInstance(Context context) { + if (sSingleton == null) { + final Resources res = context.getResources(); + final ContentResolver resolver = context.getContentResolver(); + + final String defaultServer = res.getString( + com.android.internal.R.string.config_ntpServer); + final long defaultTimeout = res.getInteger( + com.android.internal.R.integer.config_ntpTimeout); + + final String secureServer = Settings.Secure.getString( + resolver, Settings.Secure.NTP_SERVER); + final long timeout = Settings.Secure.getLong( + resolver, Settings.Secure.NTP_TIMEOUT, defaultTimeout); + + final String server = secureServer != null ? secureServer : defaultServer; + sSingleton = new NtpTrustedTime(server, timeout); + } + + return sSingleton; } /** {@inheritDoc} */ public boolean forceRefresh() { - if (mNtpServer == null) { + if (mServer == null) { // missing server, so no trusted time available return false; } + if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); - if (client.requestTime(mNtpServer, (int) mNtpTimeout)) { + if (client.requestTime(mServer, (int) mTimeout)) { mHasCache = true; mCachedNtpTime = client.getNtpTime(); mCachedNtpElapsedRealtime = client.getNtpTimeReference(); @@ -89,9 +119,19 @@ public class NtpTrustedTime implements TrustedTime { if (!mHasCache) { throw new IllegalStateException("Missing authoritative time source"); } + if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit"); // current time is age after the last ntp cache; callers who // want fresh values will hit makeAuthoritative() first. return mCachedNtpTime + getCacheAge(); } + + public long getCachedNtpTime() { + if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit"); + return mCachedNtpTime; + } + + public long getCachedNtpTimeReference() { + return mCachedNtpElapsedRealtime; + } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 9f05cbcba55c..1f2b7fbae95c 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -660,4 +660,9 @@ extremely limited. --> false + + pool.ntp.org + + 20000 + diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java index 15f22c0b2ad5..f7fe39ecfd68 100644 --- a/services/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/java/com/android/server/NetworkTimeUpdateService.java @@ -16,8 +16,6 @@ package com.android.server; -import com.android.internal.telephony.TelephonyIntents; - import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -28,7 +26,6 @@ import android.content.IntentFilter; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.net.SntpClient; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -36,12 +33,10 @@ import android.os.Message; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; -import android.util.Slog; +import android.util.NtpTrustedTime; +import android.util.TrustedTime; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; +import com.android.internal.telephony.TelephonyIntents; /** * Monitors the network time and updates the system time if it is out of sync @@ -68,14 +63,11 @@ public class NetworkTimeUpdateService { private static final long POLLING_INTERVAL_SHORTER_MS = 60 * 1000L; // 60 seconds /** Number of times to try again */ private static final int TRY_AGAIN_TIMES_MAX = 3; - /** How long to wait for the NTP server to respond. */ - private static final int MAX_NTP_FETCH_WAIT_MS = 20 * 1000; /** If the time difference is greater than this threshold, then update the time. */ private static final int TIME_ERROR_THRESHOLD_MS = 5 * 1000; private static final String ACTION_POLL = "com.android.server.NetworkTimeUpdateService.action.POLL"; - private static final String PROPERTIES_FILE = "/etc/gps.conf"; private static int POLL_REQUEST = 0; private static final long NOT_SET = -1; @@ -84,14 +76,14 @@ public class NetworkTimeUpdateService { private long mNitzZoneSetTime = NOT_SET; private Context mContext; + private TrustedTime mTime; + // NTP lookup is done on this thread and handler private Handler mHandler; private HandlerThread mThread; private AlarmManager mAlarmManager; private PendingIntent mPendingPollIntent; private SettingsObserver mSettingsObserver; - // Address of the NTP server - private String mNtpServer; // The last time that we successfully fetched the NTP time. private long mLastNtpFetchTime = NOT_SET; // Keeps track of how many quick attempts were made to fetch NTP time. @@ -101,6 +93,7 @@ public class NetworkTimeUpdateService { public NetworkTimeUpdateService(Context context) { mContext = context; + mTime = NtpTrustedTime.getInstance(context); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); Intent pollIntent = new Intent(ACTION_POLL, null); mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0); @@ -108,12 +101,6 @@ public class NetworkTimeUpdateService { /** Initialize the receivers and initiate the first NTP request */ public void systemReady() { - mNtpServer = getNtpServerAddress(); - if (mNtpServer == null) { - Slog.e(TAG, "NTP server address not found, not syncing to NTP time"); - return; - } - registerForTelephonyIntents(); registerForAlarms(); registerForConnectivityIntents(); @@ -128,27 +115,6 @@ public class NetworkTimeUpdateService { mSettingsObserver.observe(mContext); } - private String getNtpServerAddress() { - String serverAddress = null; - FileInputStream stream = null; - try { - Properties properties = new Properties(); - File file = new File(PROPERTIES_FILE); - stream = new FileInputStream(file); - properties.load(stream); - serverAddress = properties.getProperty("NTP_SERVER", null); - } catch (IOException e) { - Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (Exception e) {} - } - } - return serverAddress; - } - private void registerForTelephonyIntents() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME); @@ -189,9 +155,15 @@ public class NetworkTimeUpdateService { if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + POLLING_INTERVAL_MS || event == EVENT_AUTO_TIME_CHANGED) { if (DBG) Log.d(TAG, "Before Ntp fetch"); - long ntp = getNtpTime(); - if (DBG) Log.d(TAG, "Ntp = " + ntp); - if (ntp > 0) { + + // force refresh NTP cache when outdated + if (mTime.getCacheAge() >= POLLING_INTERVAL_MS) { + mTime.forceRefresh(); + } + + // only update when NTP time is fresh + if (mTime.getCacheAge() < POLLING_INTERVAL_MS) { + final long ntp = mTime.currentTimeMillis(); mTryAgainCounter = 0; mLastNtpFetchTime = SystemClock.elapsedRealtime(); if (Math.abs(ntp - currentTime) > TIME_ERROR_THRESHOLD_MS) { @@ -232,15 +204,6 @@ public class NetworkTimeUpdateService { mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent); } - private long getNtpTime() { - SntpClient client = new SntpClient(); - if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT_MS)) { - return client.getNtpTime(); - } else { - return 0; - } - } - /** * Checks if the user prefers to automatically set the time. */ diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index d81dfdbc1b8d..24d4dd3451d0 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -16,9 +16,6 @@ package com.android.server; -import com.android.internal.R; -import com.android.internal.telephony.TelephonyProperties; - import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; @@ -54,6 +51,9 @@ import android.util.NtpTrustedTime; import android.util.Slog; import android.util.TrustedTime; +import com.android.internal.R; +import com.android.internal.telephony.TelephonyProperties; + import java.io.BufferedWriter; import java.io.File; import java.io.FileDescriptor; @@ -63,7 +63,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.Calendar; import java.util.GregorianCalendar; -import java.util.Properties; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -87,7 +86,6 @@ public class ThrottleService extends IThrottleManager.Stub { private static final long TESTING_THRESHOLD = 1 * 1024 * 1024; private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000; - private static final long MAX_NTP_FETCH_WAIT = 20 * 1000; private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE; @@ -127,8 +125,6 @@ public class ThrottleService extends IThrottleManager.Stub { private static final int THROTTLE_INDEX_UNINITIALIZED = -1; private static final int THROTTLE_INDEX_UNTHROTTLED = 0; - private static final String PROPERTIES_FILE = "/etc/gps.conf"; - private Intent mPollStickyBroadcast; private TrustedTime mTime; @@ -139,8 +135,7 @@ public class ThrottleService extends IThrottleManager.Stub { } public ThrottleService(Context context) { - // TODO: move to using cached NtpTrustedTime - this(context, getNetworkManagementService(), new NtpTrustedTime(), + this(context, getNetworkManagementService(), NtpTrustedTime.getInstance(context), context.getResources().getString(R.string.config_datause_iface)); } @@ -341,26 +336,6 @@ public class ThrottleService extends IThrottleManager.Stub { } }, new IntentFilter(ACTION_RESET)); - FileInputStream stream = null; - try { - Properties properties = new Properties(); - File file = new File(PROPERTIES_FILE); - stream = new FileInputStream(file); - properties.load(stream); - final String ntpServer = properties.getProperty("NTP_SERVER", null); - if (mTime instanceof NtpTrustedTime) { - ((NtpTrustedTime) mTime).setNtpServer(ntpServer, MAX_NTP_FETCH_WAIT); - } - } catch (IOException e) { - Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (Exception e) {} - } - } - // use a new thread as we don't want to stall the system for file writes mThread = new HandlerThread(TAG); mThread.start(); diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index 4fa3bda0b13f..c813d3769ca8 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -32,7 +32,6 @@ import android.location.LocationManager; import android.location.LocationProvider; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.net.SntpClient; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -51,6 +50,7 @@ import android.telephony.SmsMessage; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.util.Log; +import android.util.NtpTrustedTime; import android.util.SparseIntArray; import com.android.internal.app.IBatteryStats; @@ -61,7 +61,7 @@ import com.android.internal.telephony.Phone; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.StringBufferInputStream; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; import java.util.Map.Entry; @@ -235,13 +235,13 @@ public class GpsLocationProvider implements LocationProviderInterface { // properties loaded from PROPERTIES_FILE private Properties mProperties; - private String mNtpServer; private String mSuplServerHost; private int mSuplServerPort; private String mC2KServerHost; private int mC2KServerPort; private final Context mContext; + private final NtpTrustedTime mNtpTime; private final ILocationManager mLocationManager; private Location mLocation = new Location(LocationManager.GPS_PROVIDER); private Bundle mLocationExtras = new Bundle(); @@ -286,10 +286,6 @@ public class GpsLocationProvider implements LocationProviderInterface { // current setting - 5 minutes private static final long RETRY_INTERVAL = 5*60*1000; - // to avoid injecting bad NTP time, we reject any time fixes that differ from system time - // by more than 5 minutes. - private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000; - private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() { public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException { if (listener == null) { @@ -378,6 +374,7 @@ public class GpsLocationProvider implements LocationProviderInterface { public GpsLocationProvider(Context context, ILocationManager locationManager) { mContext = context; + mNtpTime = NtpTrustedTime.getInstance(context); mLocationManager = locationManager; mNIHandler = new GpsNetInitiatedHandler(context); @@ -418,7 +415,6 @@ public class GpsLocationProvider implements LocationProviderInterface { FileInputStream stream = new FileInputStream(file); mProperties.load(stream); stream.close(); - mNtpServer = mProperties.getProperty("NTP_SERVER", null); mSuplServerHost = mProperties.getProperty("SUPL_HOST"); String portString = mProperties.getProperty("SUPL_PORT"); @@ -530,13 +526,18 @@ public class GpsLocationProvider implements LocationProviderInterface { } mInjectNtpTimePending = false; - SntpClient client = new SntpClient(); long delay; - if (client.requestTime(mNtpServer, 10000)) { - long time = client.getNtpTime(); - long timeReference = client.getNtpTimeReference(); - int certainty = (int)(client.getRoundTripTime()/2); + // force refresh NTP cache when outdated + if (mNtpTime.getCacheAge() >= NTP_INTERVAL) { + mNtpTime.forceRefresh(); + } + + // only update when NTP time is fresh + if (mNtpTime.getCacheAge() < NTP_INTERVAL) { + long time = mNtpTime.getCachedNtpTime(); + long timeReference = mNtpTime.getCachedNtpTimeReference(); + long certainty = mNtpTime.getCacheCertainty(); long now = System.currentTimeMillis(); Log.d(TAG, "NTP server returned: " @@ -545,7 +546,7 @@ public class GpsLocationProvider implements LocationProviderInterface { + " certainty: " + certainty + " system time offset: " + (time - now)); - native_inject_time(time, timeReference, certainty); + native_inject_time(time, timeReference, (int) certainty); delay = NTP_INTERVAL; } else { if (DEBUG) Log.d(TAG, "requestTime failed"); @@ -1395,7 +1396,7 @@ public class GpsLocationProvider implements LocationProviderInterface { Properties extraProp = new Properties(); try { - extraProp.load(new StringBufferInputStream(extras)); + extraProp.load(new StringReader(extras)); } catch (IOException e) { diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 2a17cbe7afda..d23d0f4564e4 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -204,9 +204,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { public NetworkPolicyManagerService(Context context, IActivityManager activityManager, IPowerManager powerManager, INetworkStatsService networkStats, INetworkManagementService networkManagement) { - // TODO: move to using cached NtpTrustedTime this(context, activityManager, powerManager, networkStats, networkManagement, - new NtpTrustedTime(), getSystemDir()); + NtpTrustedTime.getInstance(context), getSystemDir()); } private static File getSystemDir() { diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index b4bd17690605..b6834f66341c 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -27,7 +27,6 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; -import static android.provider.Settings.Secure.NETSTATS_ENABLED; import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD; @@ -71,7 +70,6 @@ import android.util.Slog; import android.util.TrustedTime; import com.android.internal.os.AtomicFile; -import com.android.server.NativeDaemonConnectorException; import com.google.android.collect.Maps; import com.google.android.collect.Sets; @@ -175,9 +173,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStatsService( Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) { - // TODO: move to using cached NtpTrustedTime - this(context, networkManager, alarmManager, new NtpTrustedTime(), getSystemDir(), - new DefaultNetworkStatsSettings(context)); + this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context), + getSystemDir(), new DefaultNetworkStatsSettings(context)); } private static File getSystemDir() { -- cgit v1.2.3-59-g8ed1b