132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong/*
232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * Copyright (C) 2015 The Android Open Source Project
332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong *
432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * Licensed under the Apache License, Version 2.0 (the "License");
532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * you may not use this file except in compliance with the License.
632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * You may obtain a copy of the License at
732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong *
832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong *      http://www.apache.org/licenses/LICENSE-2.0
932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong *
1032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * Unless required by applicable law or agreed to in writing, software
1132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * distributed under the License is distributed on an "AS IS" BASIS,
1232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * See the License for the specific language governing permissions and
1432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong * limitations under the License.
1532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong */
1632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
1732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongpackage android.net;
1832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
19dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewiczimport android.content.Context;
20dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewiczimport android.test.AndroidTestCase;
2132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport android.util.Log;
2232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport libcore.util.HexEncoding;
2332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
2432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.io.IOException;
2532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.net.DatagramPacket;
2632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.net.DatagramSocket;
2732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.net.InetAddress;
2832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.net.SocketException;
2932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wongimport java.util.Arrays;
3032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
3132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
32dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewiczpublic class SntpClientTest extends AndroidTestCase {
3332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final String TAG = "SntpClientTest";
3432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
3532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final int ORIGINATE_TIME_OFFSET = 24;
3632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final int TRANSMIT_TIME_OFFSET = 40;
3732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
3832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final int NTP_MODE_SERVER = 4;
3932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final int NTP_MODE_BROADCAST = 5;
4032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
4132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    // From tcpdump (admittedly, an NTPv4 packet):
4232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //
4332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    // Server, Leap indicator:  (0), Stratum 2 (secondary reference), poll 6 (64s), precision -20
4432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    // Root Delay: 0.005447, Root dispersion: 0.002716, Reference-ID: 221.253.71.41
4532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //   Reference Timestamp:  3653932102.507969856 (2015/10/15 14:08:22)
4632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //   Originator Timestamp: 3653932113.576327741 (2015/10/15 14:08:33)
4732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //   Receive Timestamp:    3653932113.581012725 (2015/10/15 14:08:33)
4832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //   Transmit Timestamp:   3653932113.581012725 (2015/10/15 14:08:33)
4932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //     Originator - Receive Timestamp:  +0.004684958
5032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    //     Originator - Transmit Timestamp: +0.004684958
5132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static final String WORKING_VERSION4 =
5232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "240206ec" +
5332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "00000165" +
5432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "000000b2" +
5532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "ddfd4729" +
5632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "d9ca9446820a5000" +
5732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "d9ca9451938a3771" +
5832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "d9ca945194bd3fff" +
5932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            "d9ca945194bd4001";
6032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
6132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private final SntpTestServer mServer = new SntpTestServer();
6232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private final SntpClient mClient = new SntpClient();
6332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
64dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz    private Network mNetwork;
65dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz
66dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz    @Override
67dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz    protected void setUp() throws Exception {
68dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        super.setUp();
69dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        ConnectivityManager mCM = getContext().getSystemService(ConnectivityManager.class);
70dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        mNetwork = mCM.getActiveNetwork();
71dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz    }
72dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz
7332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testBasicWorkingSntpClientQuery() throws Exception {
7432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        mServer.setServerReply(HexEncoding.decode(WORKING_VERSION4.toCharArray(), false));
75dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        assertTrue(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
7632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRequestsReceived());
7732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRepliesSent());
7832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
7932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
8032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testDnsResolutionFailure() throws Exception {
81dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork));
8232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
8332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
8432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testTimeoutFailure() throws Exception {
8532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        mServer.clearServerReply();
86dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
8732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRequestsReceived());
8832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(0, mServer.numRepliesSent());
8932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
9032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
9132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testIgnoreLeapNoSync() throws Exception {
9232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
9332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        reply[0] |= (byte) 0xc0;
9432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        mServer.setServerReply(reply);
95dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
9632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRequestsReceived());
9732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRepliesSent());
9832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
9932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
10032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testAcceptOnlyServerAndBroadcastModes() throws Exception {
10132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
10232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        for (int i = 0; i <= 7; i++) {
10332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            final String logMsg = "mode: " + i;
10432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            reply[0] &= (byte) 0xf8;
10532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            reply[0] |= (byte) i;
10632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mServer.setServerReply(reply);
107dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500,
108dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz                    mNetwork);
10932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            switch (i) {
11032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                case NTP_MODE_SERVER:
11132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                case NTP_MODE_BROADCAST:
11232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    assertTrue(logMsg, rval);
11332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    break;
11432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                default:
11532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    assertFalse(logMsg, rval);
11632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    break;
11732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            }
11832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            assertEquals(logMsg, 1, mServer.numRequestsReceived());
11932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            assertEquals(logMsg, 1, mServer.numRepliesSent());
12032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
12132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
12232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
12332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testAcceptableStrataOnly() throws Exception {
12432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final int STRATUM_MIN = 1;
12532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final int STRATUM_MAX = 15;
12632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
12732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
12832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        for (int i = 0; i < 256; i++) {
12932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            final String logMsg = "stratum: " + i;
13032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            reply[1] = (byte) i;
13132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mServer.setServerReply(reply);
132dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz            final boolean rval = mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500,
133dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz                    mNetwork);
13432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            if (STRATUM_MIN <= i && i <= STRATUM_MAX) {
13532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                assertTrue(logMsg, rval);
13632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            } else {
13732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                assertFalse(logMsg, rval);
13832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            }
13932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            assertEquals(logMsg, 1, mServer.numRequestsReceived());
14032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            assertEquals(logMsg, 1, mServer.numRepliesSent());
14132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
14232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
14332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
14432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    public void testZeroTransmitTime() throws Exception {
14532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        final byte[] reply = HexEncoding.decode(WORKING_VERSION4.toCharArray(), false);
14632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        Arrays.fill(reply, TRANSMIT_TIME_OFFSET, TRANSMIT_TIME_OFFSET + 8, (byte) 0x00);
14732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        mServer.setServerReply(reply);
148dfdd82e84fcd102ab9b4d2233d195a013914c2aeKurt Marcinkiewicz        assertFalse(mClient.requestTime(mServer.getAddress(), mServer.getPort(), 500, mNetwork));
14932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRequestsReceived());
15032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        assertEquals(1, mServer.numRepliesSent());
15132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
15232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
15332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
15432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    private static class SntpTestServer {
15532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private final Object mLock = new Object();
15632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private final DatagramSocket mSocket;
15732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private final InetAddress mAddress;
15832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private final int mPort;
15932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private byte[] mReply;
16032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private int mRcvd;
16132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private int mSent;
16232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private Thread mListeningThread;
16332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
16432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public SntpTestServer() {
16532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mSocket = makeSocket();
16632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mAddress = mSocket.getLocalAddress();
16732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mPort = mSocket.getLocalPort();
16832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            Log.d(TAG, "testing server listening on (" + mAddress + ", " + mPort + ")");
16932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
17032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mListeningThread = new Thread() {
17132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                public void run() {
17232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    while (true) {
17332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        byte[] buffer = new byte[512];
17432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        DatagramPacket ntpMsg = new DatagramPacket(buffer, buffer.length);
17532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        try {
17632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            mSocket.receive(ntpMsg);
17732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        } catch (IOException e) {
17832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            Log.e(TAG, "datagram receive error: " + e);
17932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            break;
18032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        }
18132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        synchronized (mLock) {
18232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            mRcvd++;
18332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            if (mReply == null) { continue; }
18432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            // Copy transmit timestamp into originate timestamp.
18532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            // TODO: bounds checking.
18632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            System.arraycopy(ntpMsg.getData(), TRANSMIT_TIME_OFFSET,
18732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                                             mReply, ORIGINATE_TIME_OFFSET, 8);
18832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            ntpMsg.setData(mReply);
18932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            ntpMsg.setLength(mReply.length);
19032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            try {
19132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                                mSocket.send(ntpMsg);
19232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            } catch (IOException e) {
19332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                                Log.e(TAG, "datagram send error: " + e);
19432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                                break;
19532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            }
19632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                            mSent++;
19732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                        }
19832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    }
19932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                    mSocket.close();
20032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                }
20132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            };
20232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            mListeningThread.start();
20332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
20432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
20532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        private DatagramSocket makeSocket() {
20632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            DatagramSocket socket;
20732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            try {
20832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                socket = new DatagramSocket(0, InetAddress.getLoopbackAddress());
20932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            } catch (SocketException e) {
21032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                Log.e(TAG, "Failed to create test server socket: " + e);
21132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                return null;
21232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            }
21332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            return socket;
21432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
21532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
21632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public void clearServerReply() {
21732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            setServerReply(null);
21832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
21932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
22032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public void setServerReply(byte[] reply) {
22132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            synchronized (mLock) {
22232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                mReply = reply;
22332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                mRcvd = 0;
22432d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong                mSent = 0;
22532d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong            }
22632d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        }
22732d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong
22832d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public InetAddress getAddress() { return mAddress; }
22932d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public int getPort() { return mPort; }
23032d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public int numRequestsReceived() { synchronized (mLock) { return mRcvd; } }
23132d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong        public int numRepliesSent() { synchronized (mLock) { return mSent; } }
23232d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong    }
23332d52f344aa564154b96cadc2dda3f0de3d0f455Jerry Wong}
234