Loading core/java/android/util/NtpTrustedTime.java +120 −90 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -325,7 +347,6 @@ public abstract class NtpTrustedTime implements TrustedTime { } return false; } } @GuardedBy("this") private NtpConfig getNtpConfig() { Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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 Loading core/tests/coretests/src/android/util/NtpTrustedTimeTest.java +107 −57 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java +38 −25 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -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. Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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 = Loading Loading @@ -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: Loading @@ -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. Loading @@ -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; } } Loading @@ -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; } Loading Loading @@ -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:"); Loading Loading
core/java/android/util/NtpTrustedTime.java +120 −90 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -325,7 +347,6 @@ public abstract class NtpTrustedTime implements TrustedTime { } return false; } } @GuardedBy("this") private NtpConfig getNtpConfig() { Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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 Loading
core/tests/coretests/src/android/util/NtpTrustedTimeTest.java +107 −57 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java +38 −25 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -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. Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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 = Loading Loading @@ -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: Loading @@ -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. Loading @@ -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; } } Loading @@ -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; } Loading Loading @@ -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:"); Loading