Wrong time on Android / Chrony in Termux

mk16.de

I recently tried sping in Termux. sping is a protocol that can measure asymmetric latency and asymmetric packet loss. This means that sping can tell me how long a packet takes to get to the other peer and how long it takes to get back from the peer to me. In addition, if a packet is lost, sping can tell me on which of these two routes - outbound or return - it was lost. This is particularly helpful if the outward and return routes to the peer are different. The phenomenon that the outbound and return routes are different is also known as “asymmetric routing”.

Now I wanted to try this out on my smartphone in Termux. So I downloaded a sping implementation and tested it with my server. The result was as follows:

[fd00:8e13:ce5d::1] RX: -594.034314ms TX: 650.83909ms [Loss RX: 1/32 | Loss TX: 0/32]

If you interpret the result, this means that my smartphone received the response packet about half a second before the server even sent it. This is of course not possible. In general, such an output indicates that the clocks of the two peers are not synchronized. As only the time difference is measured, it is irrelevant whether the clocks are correct - as long as both are synchronized. The phenomenon arises because the response packet contains the time at which the server processed and sent the packet. When it arrives at the other peer, the difference between the time of arrival of the packet and the time at which it was sent (the information in the packet itself) is calculated. In this case, such an incorrect clock has also led to a packet being marked as “lost”.

Which clock is wrong?

On my server, on which I had installed my sping server, I have chrony - a well-known NTP daemon - running. After checking that it is running as desired, I took a closer look at the time on my smartphone. This is running LineageOS (Android). I now wanted to find out whether the clock on my smartphone was wrong and if so, by how many seconds.

To do this, I installed chrony. I later wrote a script for the installation and sent a request to Termux asking if chrony could be included in the Termux package repository.

The result was as follows:

$ chronyd -Q -t 3 'server ptbtime1.ptb.de iburst maxsamples 1'
2023-11-14T17:34:36Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:34:36Z Disabled control of system clock
2023-11-14T17:34:40Z System clock wrong by -1.282094 seconds (ignored)
2023-11-14T17:34:40Z chronyd exiting
$ chronyd -Q -t 3 'server ptbtime4.ptb.de iburst maxsamples 1'
2023-11-14T17:34:53Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:34:53Z Disabled control of system clock
2023-11-14T17:34:57Z System clock wrong by -1.275957 seconds (ignored)
2023-11-14T17:34:57Z chronyd exiting
$ chronyd -Q -t 3 'server time.cloudflare.com iburst maxsamples 1'
2023-11-14T17:35:02Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:35:02Z Disabled control of system clock
2023-11-14T17:35:06Z System clock wrong by -1.281283 seconds (ignored)
2023-11-14T17:35:06Z chronyd exiting

I had chrony check the time with different servers as a reference. You can see that the clock on my smartphone is about 1.2 seconds ahead, which explains the output of sping.

Script

CHRONY_VERSION is replaced by the current version of chrony.

#!/data/data/com.termux/files/usr/bin/bash

CHRONY_VERSION=4.4

die () {
    >&2 echo "$1"
    exit 1
}

pkg install -y build-essential clang pkg-config readline libtomcrypt libnettle libnss libgnutls libcap gnupg || die "Could not install all required packages."

curl "https://chrony-project.org/releases/chrony-${CHRONY_VERSION}.tar.gz" --output "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not download chrony."
curl "https://chrony-project.org/releases/chrony-${CHRONY_VERSION}-tar-gz-asc.txt" --output "chrony-${CHRONY_VERSION}-tar-gz-asc.txt" || die "Could not download the GPG signature from chrony."

gpg --keyserver "keyserver.ubuntu.com" --recv-keys "8F375C7E8D0EE125A3D3BD51537E2B76F7680DAC" || die "Could not download the GPG key to verify the signature."

gpg --verify "chrony-${CHRONY_VERSION}-tar-gz-asc.txt" "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not verify the signature."

tar xzf "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not extract the chrony download."
# x = extract
# z = gzip
# f = file

(
    cd "chrony-${CHRONY_VERSION}/" || die "Could not change to the downloaded directory of chrony."

    # chrony can currently (not yet) adjust the time on Android, see https://gitlab.com/chrony/chrony/-/issues/1
    # For the build to be successful, this functionality must be deactivated with `--disable-refclock`.
    ./configure \
        --disable-refclock \
        --prefix="/data/data/com.termux/files/usr/" \
        --sysconfdir="/data/data/com.termux/files/usr/etc" \
        --localstatedir="/data/data/com.termux/files/usr/var" \
            || die "Could not successfully perform the preparation of the compilation of chrony."
    make -j "$(nproc)" || die "Could not compile chrony successfully."
    make install || die "Could not install chrony successfully."
)

Update to chrony in Termux Package Repository: @sylirre has managed to create a build script for Termux. It is now available in the package repositories.