Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddafb64f authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Cached NTP time for system services."

parents 38715a8d 104344e5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
         */
+50 −10
Original line number Diff line number Diff line
@@ -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;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -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>
+15 −52
Original line number Diff line number Diff line
@@ -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.
     */
+4 −29
Original line number Diff line number Diff line
@@ -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();
Loading