Merge "Cached NTP time for system services."

This commit is contained in:
Jeff Sharkey
2011-07-10 16:18:58 -07:00
committed by Android (Google) Code Review
8 changed files with 98 additions and 113 deletions

View File

@@ -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
*/

View File

@@ -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;
}
}

View File

@@ -660,4 +660,9 @@
extremely limited. -->
<bool name="config_allowActionMenuItemTextWithIcon">false</bool>
<!-- Remote server that can provide NTP responses. -->
<string translatable="false" name="config_ntpServer">pool.ntp.org</string>
<!-- Timeout to wait for NTP server response. -->
<integer name="config_ntpTimeout">20000</integer>
</resources>

View File

@@ -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.
*/

View File

@@ -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();

View File

@@ -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)
{

View File

@@ -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() {

View File

@@ -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() {