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

Commit 271dfbe8 authored by Neil Fuller's avatar Neil Fuller Committed by Gerrit Code Review
Browse files

Merge "Make NTP config configurable from cmd"

parents a29bc7bb 030a6921
Loading
Loading
Loading
Loading
+69 −15
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ import android.text.TextUtils;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import java.util.function.Supplier;

@@ -96,8 +99,8 @@ public class NtpTrustedTime implements TrustedTime {
        @Override
        public String toString() {
            return "TimeResult{"
                    + "mTimeMillis=" + mTimeMillis
                    + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
                    + "mTimeMillis=" + Instant.ofEpochMilli(mTimeMillis)
                    + ", mElapsedRealtimeMillis=" + Duration.ofMillis(mElapsedRealtimeMillis)
                    + ", mCertaintyMillis=" + mCertaintyMillis
                    + '}';
        }
@@ -131,6 +134,14 @@ public class NtpTrustedTime implements TrustedTime {
        }
    };

    /** An in-memory config override for use during tests. */
    @Nullable
    private String mHostnameForTests;

    /** An in-memory config override for use during tests. */
    @Nullable
    private Duration mTimeoutForTests;

    // Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
    // forceRefresh().
    private volatile TimeResult mTimeResult;
@@ -148,12 +159,23 @@ public class NtpTrustedTime implements TrustedTime {
        return sSingleton;
    }

    /**
     * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
     * test value, i.e. so the normal value will be used next time.
     */
    public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
        synchronized (this) {
            mHostnameForTests = hostname;
            mTimeoutForTests = timeout;
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean forceRefresh() {
        synchronized (this) {
            NtpConnectionInfo connectionInfo = getNtpConnectionInfo();
            if (connectionInfo == null) {
                // missing server config, so no trusted time available
                // missing server config, so no NTP time available
                if (LOGD) Log.d(TAG, "forceRefresh: invalid server config");
                return false;
            }
@@ -290,6 +312,14 @@ public class NtpTrustedTime implements TrustedTime {
        int getTimeoutMillis() {
            return mTimeoutMillis;
        }

        @Override
        public String toString() {
            return "NtpConnectionInfo{"
                    + "mServer='" + mServer + '\''
                    + ", mTimeoutMillis=" + mTimeoutMillis
                    + '}';
        }
    }

    @GuardedBy("this")
@@ -297,17 +327,41 @@ public class NtpTrustedTime implements TrustedTime {
        final ContentResolver resolver = mContext.getContentResolver();

        final Resources res = mContext.getResources();
        final String defaultServer = res.getString(
                com.android.internal.R.string.config_ntpServer);
        final int defaultTimeoutMillis = res.getInteger(
                com.android.internal.R.integer.config_ntpTimeout);

        final String secureServer = Settings.Global.getString(
                resolver, Settings.Global.NTP_SERVER);
        final int timeoutMillis = Settings.Global.getInt(

        final String hostname;
        if (mHostnameForTests != null) {
            hostname = mHostnameForTests;
        } else {
            String serverGlobalSetting =
                    Settings.Global.getString(resolver, Settings.Global.NTP_SERVER);
            if (serverGlobalSetting != null) {
                hostname = serverGlobalSetting;
            } else {
                hostname = res.getString(com.android.internal.R.string.config_ntpServer);
            }
        }

        final int timeoutMillis;
        if (mTimeoutForTests != null) {
            timeoutMillis = (int) mTimeoutForTests.toMillis();
        } else {
            int defaultTimeoutMillis =
                    res.getInteger(com.android.internal.R.integer.config_ntpTimeout);
            timeoutMillis = Settings.Global.getInt(
                    resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
        }
        return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
    }

        final String server = secureServer != null ? secureServer : defaultServer;
        return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis);
    /** Prints debug information. */
    public void dump(PrintWriter pw) {
        synchronized (this) {
            pw.println("getNtpConnectionInfo()=" + getNtpConnectionInfo());
            pw.println("mTimeResult=" + mTimeResult);
            if (mTimeResult != null) {
                pw.println("mTimeResult.getAgeMillis()="
                        + Duration.ofMillis(mTimeResult.getAgeMillis()));
            }
        }
    }
}
+23 −12
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.timedetector.NetworkTimeSuggestion;
@@ -45,12 +46,12 @@ import android.util.LocalLog;
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.NtpTrustedTime.TimeResult;
import android.util.TimeUtils;

import com.android.internal.util.DumpUtils;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.time.Duration;

/**
 * Monitors the network time. If looking up the network time fails for some reason, it tries a few
@@ -191,6 +192,19 @@ public class NetworkTimeUpdateService extends Binder {
        return success;
    }

    /**
     * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
     * test value, i.e. so the normal value will be used next time.
     */
    void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.SET_TIME, "set NTP server config for tests");

        mLocalLog.log("Setting server config for tests: hostname=" + hostname
                + ", timeout=" + timeout);
        mTime.setServerConfigForTests(hostname, timeout);
    }

    private void onPollNetworkTime(int event) {
        // If we don't have any default network, don't bother.
        if (mDefaultNetwork == null) return;
@@ -349,17 +363,14 @@ public class NetworkTimeUpdateService extends Binder {
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        pw.print("PollingIntervalMs: ");
        TimeUtils.formatDuration(mPollingIntervalMs, pw);
        pw.print("\nPollingIntervalShorterMs: ");
        TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
        pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
        pw.println("\nTryAgainCounter: " + mTryAgainCounter);
        NtpTrustedTime.TimeResult ntpResult = mTime.getCachedTimeResult();
        pw.println("NTP cache result: " + ntpResult);
        if (ntpResult != null) {
            pw.println("NTP result age: " + ntpResult.getAgeMillis());
        }
        pw.println("mPollingIntervalMs=" + Duration.ofMillis(mPollingIntervalMs));
        pw.println("mPollingIntervalShorterMs=" + Duration.ofMillis(mPollingIntervalShorterMs));
        pw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
        pw.println("mTryAgainCounter=" + mTryAgainCounter);
        pw.println();
        pw.println("NtpTrustedTime:");
        mTime.dump(pw);
        pw.println();
        pw.println("Local logs:");
        mLocalLog.dump(fd, pw, args);
        pw.println();
+39 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.os.ShellCommand;

import java.io.PrintWriter;
import java.time.Duration;
import java.util.Objects;

/** Implements the shell command interface for {@link NetworkTimeUpdateService}. */
@@ -40,6 +41,13 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
     */
    private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh";

    /**
     * A shell command that sets the NTP server config for tests. Config is cleared on reboot.
     */
    private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
    private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
    private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";

    @NonNull
    private final NetworkTimeUpdateService mNetworkTimeUpdateService;

@@ -58,6 +66,8 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
                return runClearTime();
            case SHELL_COMMAND_FORCE_REFRESH:
                return runForceRefresh();
            case SHELL_COMMAND_SET_SERVER_CONFIG:
                return runSetServerConfig();
            default: {
                return handleDefaultCommands(cmd);
            }
@@ -75,6 +85,29 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
        return 0;
    }

    private int runSetServerConfig() {
        String hostname = null;
        Duration timeout = null;
        String opt;
        while ((opt = getNextArg()) != null) {
            switch (opt) {
                case SET_SERVER_CONFIG_HOSTNAME_ARG: {
                    hostname = getNextArgRequired();
                    break;
                }
                case SET_SERVER_CONFIG_TIMEOUT_ARG: {
                    timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
                    break;
                }
                default: {
                    throw new IllegalArgumentException("Unknown option: " + opt);
                }
            }
        }
        mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
        return 0;
    }

    @Override
    public void onHelp() {
        final PrintWriter pw = getOutPrintWriter();
@@ -85,6 +118,12 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
        pw.printf("    Clears the latest time.\n");
        pw.printf("  %s\n", SHELL_COMMAND_FORCE_REFRESH);
        pw.printf("    Refreshes the latest time. Prints whether it was successful.\n");
        pw.printf("  %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
        pw.printf("    Sets the NTP server config for tests. The config is not persisted.\n");
        pw.printf("      Options: [%s <hostname>] [%s <millis>]\n",
                SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
        pw.printf("      Each key/value is optional and must be specified to override the\n");
        pw.printf("      normal value, not specifying a key causes it to reset to the original.\n");
        pw.println();
    }
}