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

Commit 7a4ff644 authored by Kurt Marcinkiewicz's avatar Kurt Marcinkiewicz Committed by Remi NGUYEN VAN
Browse files

Allow specifying a network for SNTP time sync

Permits syncing over a specific network instead of the default for
the process. This was causing an issue with Android Wear devices
paired with iOS where the default network is bluetooth
(see b/32663274).

This CL is in support of ag/3776564

Bug: 32663274

Test: adb shell am instrument -e class android.net.SntpClientTest -w \
com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
(cherry-pick of pi-dev Ic9fc169cf75457810d4992121d85d7642e350b90)
Merged-In: I339c77063c72a9d76a5c4cb17052e20fb6e045a6
Merged-In: I8dfd1cad99c63efdc14c174c19f094a61cdfc44f

Change-Id: I44df66688292b144ec7dfcdd9ae5d82489f82774
parent 6fa8d06c
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -80,25 +80,27 @@ public class SntpClient {
     *
     *
     * @param host host name of the server.
     * @param host host name of the server.
     * @param timeout network timeout in milliseconds.
     * @param timeout network timeout in milliseconds.
     * @param network network over which to send the request.
     * @return true if the transaction was successful.
     * @return true if the transaction was successful.
     */
     */
    public boolean requestTime(String host, int timeout) {
    public boolean requestTime(String host, int timeout, Network network) {
        InetAddress address = null;
        InetAddress address = null;
        try {
        try {
            address = InetAddress.getByName(host);
            address = network.getByName(host);
        } catch (Exception e) {
        } catch (Exception e) {
            EventLogTags.writeNtpFailure(host, e.toString());
            EventLogTags.writeNtpFailure(host, e.toString());
            if (DBG) Log.d(TAG, "request time failed: " + e);
            if (DBG) Log.d(TAG, "request time failed: " + e);
            return false;
            return false;
        }
        }
        return requestTime(address, NTP_PORT, timeout);
        return requestTime(address, NTP_PORT, timeout, network);
    }
    }


    public boolean requestTime(InetAddress address, int port, int timeout) {
    public boolean requestTime(InetAddress address, int port, int timeout, Network network) {
        DatagramSocket socket = null;
        DatagramSocket socket = null;
        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
        try {
        try {
            socket = new DatagramSocket();
            socket = new DatagramSocket();
            network.bindSocket(socket);
            socket.setSoTimeout(timeout);
            socket.setSoTimeout(timeout);
            byte[] buffer = new byte[NTP_PACKET_SIZE];
            byte[] buffer = new byte[NTP_PACKET_SIZE];
            DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port);
            DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port);
@@ -168,6 +170,12 @@ public class SntpClient {
        return true;
        return true;
    }
    }


    @Deprecated
    public boolean requestTime(String host, int timeout) {
        Log.w(TAG, "Shame on you for calling the hidden API requestTime()!");
        return false;
    }

    /**
    /**
     * Returns the time computed from the NTP transaction.
     * Returns the time computed from the NTP transaction.
     *
     *
+16 −3
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.NetworkInfo;
import android.net.SntpClient;
import android.net.SntpClient;
import android.os.SystemClock;
import android.os.SystemClock;
@@ -80,6 +81,18 @@ public class NtpTrustedTime implements TrustedTime {


    @Override
    @Override
    public boolean forceRefresh() {
    public boolean forceRefresh() {
        // We can't do this at initialization time: ConnectivityService might not be running yet.
        synchronized (this) {
            if (mCM == null) {
                mCM = sContext.getSystemService(ConnectivityManager.class);
            }
        }

        final Network network = mCM == null ? null : mCM.getActiveNetwork();
        return forceRefresh(network);
    }

    public boolean forceRefresh(Network network) {
        if (TextUtils.isEmpty(mServer)) {
        if (TextUtils.isEmpty(mServer)) {
            // missing server, so no trusted time available
            // missing server, so no trusted time available
            return false;
            return false;
@@ -88,11 +101,11 @@ public class NtpTrustedTime implements TrustedTime {
        // We can't do this at initialization time: ConnectivityService might not be running yet.
        // We can't do this at initialization time: ConnectivityService might not be running yet.
        synchronized (this) {
        synchronized (this) {
            if (mCM == null) {
            if (mCM == null) {
                mCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
                mCM = sContext.getSystemService(ConnectivityManager.class);
            }
            }
        }
        }


        final NetworkInfo ni = mCM == null ? null : mCM.getActiveNetworkInfo();
        final NetworkInfo ni = mCM == null ? null : mCM.getNetworkInfo(network);
        if (ni == null || !ni.isConnected()) {
        if (ni == null || !ni.isConnected()) {
            if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
            if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
            return false;
            return false;
@@ -101,7 +114,7 @@ public class NtpTrustedTime implements TrustedTime {


        if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
        if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
        final SntpClient client = new SntpClient();
        final SntpClient client = new SntpClient();
        if (client.requestTime(mServer, (int) mTimeout)) {
        if (client.requestTime(mServer, (int) mTimeout, network)) {
            mHasCache = true;
            mHasCache = true;
            mCachedNtpTime = client.getNtpTime();
            mCachedNtpTime = client.getNtpTime();
            mCachedNtpElapsedRealtime = client.getNtpTimeReference();
            mCachedNtpElapsedRealtime = client.getNtpTimeReference();
+21 −10
Original line number Original line Diff line number Diff line
@@ -16,7 +16,8 @@


package android.net;
package android.net;


import android.net.SntpClient;
import android.content.Context;
import android.test.AndroidTestCase;
import android.util.Log;
import android.util.Log;
import libcore.util.HexEncoding;
import libcore.util.HexEncoding;


@@ -26,10 +27,9 @@ import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketException;
import java.util.Arrays;
import java.util.Arrays;
import junit.framework.TestCase;




public class SntpClientTest extends TestCase {
public class SntpClientTest extends AndroidTestCase {
    private static final String TAG = "SntpClientTest";
    private static final String TAG = "SntpClientTest";


    private static final int ORIGINATE_TIME_OFFSET = 24;
    private static final int ORIGINATE_TIME_OFFSET = 24;
@@ -61,20 +61,29 @@ public class SntpClientTest extends TestCase {
    private final SntpTestServer mServer = new SntpTestServer();
    private final SntpTestServer mServer = new SntpTestServer();
    private final SntpClient mClient = new SntpClient();
    private final SntpClient mClient = new SntpClient();


    private Network mNetwork;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        ConnectivityManager mCM = getContext().getSystemService(ConnectivityManager.class);
        mNetwork = mCM.getActiveNetwork();
    }

    public void testBasicWorkingSntpClientQuery() throws Exception {
    public void testBasicWorkingSntpClientQuery() throws Exception {
        mServer.setServerReply(HexEncoding.decode(WORKING_VERSION4.toCharArray(), false));
        mServer.setServerReply(HexEncoding.decode(WORKING_VERSION4.toCharArray(), false));
        assertTrue(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500));
        assertTrue(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRepliesSent());
        assertEquals(1, mServer.numRepliesSent());
    }
    }


    public void testDnsResolutionFailure() throws Exception {
    public void testDnsResolutionFailure() throws Exception {
        assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000));
        assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork));
    }
    }


    public void testTimeoutFailure() throws Exception {
    public void testTimeoutFailure() throws Exception {
        mServer.clearServerReply();
        mServer.clearServerReply();
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500));
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(0, mServer.numRepliesSent());
        assertEquals(0, mServer.numRepliesSent());
    }
    }
@@ -83,7 +92,7 @@ public class SntpClientTest extends TestCase {
        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
        reply[0] |= (byte) 0xc0;
        reply[0] |= (byte) 0xc0;
        mServer.setServerReply(reply);
        mServer.setServerReply(reply);
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500));
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRepliesSent());
        assertEquals(1, mServer.numRepliesSent());
    }
    }
@@ -95,7 +104,8 @@ public class SntpClientTest extends TestCase {
            reply[0] &= (byte) 0xf8;
            reply[0] &= (byte) 0xf8;
            reply[0] |= (byte) i;
            reply[0] |= (byte) i;
            mServer.setServerReply(reply);
            mServer.setServerReply(reply);
            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500);
            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500,
                    mNetwork);
            switch (i) {
            switch (i) {
                case NTP_MODE_SERVER:
                case NTP_MODE_SERVER:
                case NTP_MODE_BROADCAST:
                case NTP_MODE_BROADCAST:
@@ -119,7 +129,8 @@ public class SntpClientTest extends TestCase {
            final String logMsg = "stratum: " + i;
            final String logMsg = "stratum: " + i;
            reply[1] = (byte) i;
            reply[1] = (byte) i;
            mServer.setServerReply(reply);
            mServer.setServerReply(reply);
            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500);
            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500,
                    mNetwork);
            if (STRATUM_MIN <= i && i <= STRATUM_MAX) {
            if (STRATUM_MIN <= i && i <= STRATUM_MAX) {
                assertTrue(logMsg, rval);
                assertTrue(logMsg, rval);
            } else {
            } else {
@@ -134,7 +145,7 @@ public class SntpClientTest extends TestCase {
        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
        Arrays.fill(reply, TRANSMIT_TIME_OFFSET, TRANSMIT_TIME_OFFSET + 8, (byte) 0x00);
        Arrays.fill(reply, TRANSMIT_TIME_OFFSET, TRANSMIT_TIME_OFFSET + 8, (byte) 0x00);
        mServer.setServerReply(reply);
        mServer.setServerReply(reply);
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500));
        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRequestsReceived());
        assertEquals(1, mServer.numRepliesSent());
        assertEquals(1, mServer.numRepliesSent());
    }
    }
+9 −3
Original line number Original line Diff line number Diff line
@@ -16,7 +16,10 @@
package com.android.tests.bandwidthenforcement;
package com.android.tests.bandwidthenforcement;


import android.app.IntentService;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.SntpClient;
import android.net.SntpClient;
import android.os.Environment;
import android.os.Environment;
import android.util.Log;
import android.util.Log;
@@ -55,7 +58,7 @@ public class BandwidthEnforcementTestService extends IntentService {
        String outputFile = intent.getStringExtra(OUTPUT_FILE);
        String outputFile = intent.getStringExtra(OUTPUT_FILE);
        dumpResult("testUrlConnection", testUrlConnection(), outputFile);
        dumpResult("testUrlConnection", testUrlConnection(), outputFile);
        dumpResult("testUrlConnectionv6", testUrlConnectionv6(), outputFile);
        dumpResult("testUrlConnectionv6", testUrlConnectionv6(), outputFile);
        dumpResult("testSntp", testSntp(), outputFile);
        dumpResult("testSntp", testSntp(getApplicationContext()), outputFile);
        dumpResult("testDns", testDns(), outputFile);
        dumpResult("testDns", testDns(), outputFile);
    }
    }


@@ -138,9 +141,12 @@ public class BandwidthEnforcementTestService extends IntentService {
     * Tests to connect via sntp.
     * Tests to connect via sntp.
     * @return true if it was able to connect, false otherwise.
     * @return true if it was able to connect, false otherwise.
     */
     */
    public static boolean testSntp() {
    public static boolean testSntp(Context context) {
        final SntpClient client = new SntpClient();
        final SntpClient client = new SntpClient();
        if (client.requestTime("0.pool.ntp.org", 10000)) {
        final ConnectivityManager mCM = context.getSystemService(ConnectivityManager.class);
        final Network network = mCM.getActiveNetwork();

        if (client.requestTime("0.pool.ntp.org", 10000, network)) {
            return true;
            return true;
        }
        }
        return false;
        return false;