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

Commit ae34fbc3 authored by Neil Fuller's avatar Neil Fuller Committed by Android (Google) Code Review
Browse files

Merge "Add NtpTrustedTime.forceRefresh(Network)"

parents c9c081c8 5ef61031
Loading
Loading
Loading
Loading
+120 −90
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * A singleton that connects with a remote NTP server as its trusted time source. This class
@@ -251,24 +250,47 @@ public abstract class NtpTrustedTime implements TrustedTime {
        }
    }

    /** Forces a refresh using the default network. */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean forceRefresh() {
        synchronized (this) {
            NtpConfig ntpConfig = getNtpConfig();
            if (ntpConfig == null) {
                // missing server config, so no NTP time available
                if (LOGD) Log.d(TAG, "forceRefresh: invalid server config");
            Network network = getDefaultNetwork();
            if (network == null) {
                if (LOGD) Log.d(TAG, "forceRefresh: no network available");
                return false;
            }

            Network network = getNetwork();
            if (network == null) {
                if (LOGD) Log.d(TAG, "forceRefresh: no network available");
            return forceRefreshLocked(network);
        }
    }

    /** Forces a refresh using the specified network. */
    public boolean forceRefresh(@NonNull Network network) {
        Objects.requireNonNull(network);

        synchronized (this) {
            return forceRefreshLocked(network);
        }
    }

    @GuardedBy("this")
    private boolean forceRefreshLocked(@NonNull Network network) {
        Objects.requireNonNull(network);

        if (!isNetworkConnected(network)) {
            if (LOGD) Log.d(TAG, "forceRefreshLocked: network=" + network + " is not connected");
            return false;
        }

        NtpConfig ntpConfig = getNtpConfig();
        if (ntpConfig == null) {
            // missing server config, so no NTP time available
            if (LOGD) Log.d(TAG, "forceRefreshLocked: invalid server config");
            return false;
        }

        if (LOGD) {
                Log.d(TAG, "forceRefresh: NTP request network=" + network
            Log.d(TAG, "forceRefreshLocked: NTP request network=" + network
                    + " ntpConfig=" + ntpConfig);
        }

@@ -325,7 +347,6 @@ public abstract class NtpTrustedTime implements TrustedTime {
        }
        return false;
    }
    }

    @GuardedBy("this")
    private NtpConfig getNtpConfig() {
@@ -346,14 +367,23 @@ public abstract class NtpTrustedTime implements TrustedTime {
    public abstract NtpConfig getNtpConfigInternal();

    /**
     * Returns the {@link Network} to use during an NTP query. This method can return {@code null}
     * if there is no connectivity
     * Returns the default {@link Network} to use during an NTP query when no network is specified.
     * This method can return {@code null} if the device hasn't fully initialized or there is no
     * active network.
     *
     * <p>This method has been made public for easy replacement during tests.
     */
    @VisibleForTesting
    @Nullable
    public abstract Network getNetwork();
    public abstract Network getDefaultNetwork();

    /**
     * Returns {@code true} if there is likely to be connectivity on the supplied network.
     *
     * <p>This method has been made public for easy replacement during tests.
     */
    @VisibleForTesting
    public abstract boolean isNetworkConnected(@NonNull Network network);

    /**
     * Queries the specified NTP server. This is a blocking call. Returns {@code null} if the query
@@ -565,26 +595,9 @@ public abstract class NtpTrustedTime implements TrustedTime {
     */
    private static final class NtpTrustedTimeImpl extends NtpTrustedTime {

        /**
         * A supplier that returns the ConnectivityManager. The Supplier can return null if
         * ConnectivityService isn't running yet.
         */
        private final Supplier<ConnectivityManager> mConnectivityManagerSupplier =
                new Supplier<>() {
        @GuardedBy("this")
        private ConnectivityManager mConnectivityManager;

            @Nullable
            @Override
            public synchronized ConnectivityManager get() {
                // We can't do this at initialization time: ConnectivityService might not be running
                // yet.
                if (mConnectivityManager == null) {
                    mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
                }
                return mConnectivityManager;
            }
        };

        @NonNull
        private final Context mContext;

@@ -629,13 +642,20 @@ public abstract class NtpTrustedTime implements TrustedTime {
        }

        @Override
        public Network getNetwork() {
            ConnectivityManager connectivityManager = mConnectivityManagerSupplier.get();
        public Network getDefaultNetwork() {
            ConnectivityManager connectivityManager = getConnectivityManager();
            if (connectivityManager == null) {
                if (LOGD) Log.d(TAG, "getNetwork: no ConnectivityManager");
                return null;
            }
            final Network network = connectivityManager.getActiveNetwork();
            return connectivityManager.getActiveNetwork();
        }

        @Override
        public boolean isNetworkConnected(@NonNull Network network) {
            ConnectivityManager connectivityManager = getConnectivityManager();
            if (connectivityManager == null) {
                return false;
            }
            final NetworkInfo ni = connectivityManager.getNetworkInfo(network);

            // This connectivity check is to avoid performing a DNS lookup for the time server on a
@@ -649,9 +669,19 @@ public abstract class NtpTrustedTime implements TrustedTime {
            // addresses are actually reachable.
            if (ni == null || !ni.isConnected()) {
                if (LOGD) Log.d(TAG, "getNetwork: no connectivity");
                return null;
                return false;
            }
            return true;
        }
            return network;

        private synchronized ConnectivityManager getConnectivityManager() {
            if (mConnectivityManager == null) {
                mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
            }
            if (mConnectivityManager == null) {
                if (LOGD) Log.d(TAG, "getConnectivityManager: no ConnectivityManager");
            }
            return mConnectivityManager;
        }

        @Override
+107 −57

File changed.

Preview size limit exceeded, changes collapsed.

+38 −25
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.server.LocalServices;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Objects;

/**
 * Monitors the network time. If looking up the network time fails for some reason, it tries a few
@@ -74,8 +75,6 @@ public class NetworkTimeUpdateService extends Binder {

    private static final int POLL_REQUEST = 0;

    private Network mDefaultNetwork = null;

    private final Context mContext;
    private final NtpTrustedTime mTime;
    private final AlarmManager mAlarmManager;
@@ -84,21 +83,12 @@ public class NetworkTimeUpdateService extends Binder {
    private final PendingIntent mPendingPollIntent;
    private final PowerManager.WakeLock mWakeLock;

    // NTP lookup is done on this thread and handler
    private Handler mHandler;
    private AutoTimeSettingObserver mAutoTimeSettingObserver;
    private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;

    // Normal polling frequency
    private final long mPollingIntervalMs;
    // Try-again polling interval, in case the network request failed
    private final long mPollingIntervalShorterMs;
    // Number of times to try again
    private final int mTryAgainTimesMax;
    // Keeps track of how many quick attempts were made to fetch NTP time.
    // During bootup, the network may not have been up yet, or it's taking time for the
    // connection to happen.
    private int mTryAgainCounter;

    /**
     * A log that records the decisions to fetch a network time update.
@@ -107,8 +97,26 @@ public class NetworkTimeUpdateService extends Binder {
    @NonNull
    private final LocalLog mLocalLog = new LocalLog(30, false /* useLocalTimestamps */);

    public NetworkTimeUpdateService(Context context) {
        mContext = context;
    // NTP lookup is done on this thread and handler
    // @NonNull after systemRunning()
    private Handler mHandler;
    // @NonNull after systemRunning()
    private AutoTimeSettingObserver mAutoTimeSettingObserver;
    // @NonNull after systemRunning()
    private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;

    // This field is only updated and accessed by the mHandler thread (except dump()).
    @Nullable
    private Network mDefaultNetwork = null;

    // Keeps track of how many quick attempts were made to fetch NTP time.
    // During bootup, the network may not have been up yet, or it's taking time for the
    // connection to happen.
    // This field is only updated and accessed by the mHandler thread (except dump()).
    private int mTryAgainCounter;

    public NetworkTimeUpdateService(@NonNull Context context) {
        mContext = Objects.requireNonNull(context);
        mTime = NtpTrustedTime.getInstance(context);
        mAlarmManager = mContext.getSystemService(AlarmManager.class);
        mTimeDetectorInternal = LocalServices.getService(TimeDetectorInternal.class);
@@ -205,23 +213,26 @@ public class NetworkTimeUpdateService extends Binder {

    private void onPollNetworkTime(int event) {
        // If we don't have any default network, don't bother.
        if (mDefaultNetwork == null) return;
        Network network = mDefaultNetwork;
        if (network == null) return;

        mWakeLock.acquire();
        try {
            onPollNetworkTimeUnderWakeLock(event);
            onPollNetworkTimeUnderWakeLock(network, event);
        } finally {
            mWakeLock.release();
        }
    }

    private void onPollNetworkTimeUnderWakeLock(int event) {
    private void onPollNetworkTimeUnderWakeLock(@NonNull Network network, int event) {
        long currentElapsedRealtimeMillis = SystemClock.elapsedRealtime();

        // Force an NTP fix when outdated
        NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult();
        if (cachedNtpResult == null || cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
                >= mPollingIntervalMs) {
            if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
            boolean isSuccessful = mTime.forceRefresh();
            if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh using network=" + network);
            boolean isSuccessful = mTime.forceRefresh(network);
            if (isSuccessful) {
                mTryAgainCounter = 0;
            } else {
@@ -265,7 +276,8 @@ public class NetworkTimeUpdateService extends Binder {
    }

    /** Suggests the time to the time detector. It may choose use it to set the system clock. */
    private void makeNetworkTimeSuggestion(TimeResult ntpResult, String debugInfo) {
    private void makeNetworkTimeSuggestion(
            @NonNull TimeResult ntpResult, @NonNull String debugInfo) {
        TimestampedValue<Long> timeSignal = new TimestampedValue<>(
                ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
        NetworkTimeSuggestion timeSuggestion =
@@ -295,7 +307,7 @@ public class NetworkTimeUpdateService extends Binder {
        }

        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case EVENT_AUTO_TIME_ENABLED:
                case EVENT_POLL_NETWORK_TIME:
@@ -308,7 +320,7 @@ public class NetworkTimeUpdateService extends Binder {

    private class NetworkTimeUpdateCallback extends NetworkCallback {
        @Override
        public void onAvailable(Network network) {
        public void onAvailable(@NonNull Network network) {
            Log.d(TAG, String.format("New default network %s; checking time.", network));
            mDefaultNetwork = network;
            // Running on mHandler so invoke directly.
@@ -316,7 +328,7 @@ public class NetworkTimeUpdateService extends Binder {
        }

        @Override
        public void onLost(Network network) {
        public void onLost(@NonNull Network network) {
            if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
        }
    }
@@ -331,10 +343,10 @@ public class NetworkTimeUpdateService extends Binder {
        private final int mMsg;
        private final Handler mHandler;

        AutoTimeSettingObserver(Context context, Handler handler, int msg) {
        AutoTimeSettingObserver(@NonNull Context context, @NonNull Handler handler, int msg) {
            super(handler);
            mContext = context;
            mHandler = handler;
            mContext = Objects.requireNonNull(context);
            mHandler = Objects.requireNonNull(handler);
            mMsg = msg;
        }

@@ -366,6 +378,7 @@ public class NetworkTimeUpdateService extends Binder {
        pw.println("mPollingIntervalMs=" + Duration.ofMillis(mPollingIntervalMs));
        pw.println("mPollingIntervalShorterMs=" + Duration.ofMillis(mPollingIntervalShorterMs));
        pw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
        pw.println("mDefaultNetwork=" + mDefaultNetwork);
        pw.println("mTryAgainCounter=" + mTryAgainCounter);
        pw.println();
        pw.println("NtpTrustedTime:");