am 6469dee2: am d15dd73c: am d26b8028: am 64bb1b75: am 799044f3: am 505ce805: Merge "Change SSLCertificateSocketFactoryTest to use googlemail.com" into jb-dev

* commit '6469dee2c0a7b6c51eafbbef339878fcc42ad962':
  Change SSLCertificateSocketFactoryTest to use googlemail.com
diff --git a/tests/cts/net/Android.mk b/tests/cts/net/Android.mk
index b327392..a6543b3 100644
--- a/tests/cts/net/Android.mk
+++ b/tests/cts/net/Android.mk
@@ -21,7 +21,9 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner voip-common
+
+LOCAL_JNI_SHARED_LIBRARIES := libnativedns_jni
 
 # include CtsTestServer as a temporary hack to free net.cts from cts.stub.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -34,3 +36,5 @@
 #LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/cts/net/jni/Android.mk b/tests/cts/net/jni/Android.mk
new file mode 100644
index 0000000..75982de
--- /dev/null
+++ b/tests/cts/net/jni/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libnativedns_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := NativeDnsJni.c
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/cts/net/jni/NativeDnsJni.c b/tests/cts/net/jni/NativeDnsJni.c
new file mode 100644
index 0000000..de9bb67
--- /dev/null
+++ b/tests/cts/net/jni/NativeDnsJni.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <arpa/inet.h>
+#include <jni.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <utils/Log.h>
+
+JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclass class)
+{
+    const char *node = "www.google.com";
+    char *service = NULL;
+    struct addrinfo *answer;
+
+    int res = getaddrinfo(node, service, NULL, &answer);
+    ALOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
+    if (res != 0) return JNI_FALSE;
+
+    // check for v4 & v6
+    {
+        int foundv4 = 0;
+        int foundv6 = 0;
+        struct addrinfo *current = answer;
+        while (current != NULL) {
+            char buf[256];
+            if (current->ai_addr->sa_family == AF_INET) {
+                inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
+                        buf, sizeof(buf));
+                foundv4 = 1;
+                ALOGD("  %s", buf);
+            } else if (current->ai_addr->sa_family == AF_INET6) {
+                inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
+                        buf, sizeof(buf));
+                foundv6 = 1;
+                ALOGD("  %s", buf);
+            }
+            current = current->ai_next;
+        }
+
+        freeaddrinfo(answer);
+        answer = NULL;
+        if (foundv4 != 1 || foundv6 != 1) {
+            ALOGD("getaddrinfo(www.google.com) didn't find both v4 and v6");
+            return JNI_FALSE;
+        }
+    }
+
+    node = "ipv6.google.com";
+    res = getaddrinfo(node, service, NULL, &answer);
+    ALOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
+    if (res != 0) return JNI_FALSE;
+
+    {
+        int foundv4 = 0;
+        int foundv6 = 0;
+        struct addrinfo *current = answer;
+        while (current != NULL) {
+            char buf[256];
+            if (current->ai_addr->sa_family == AF_INET) {
+                inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
+                        buf, sizeof(buf));
+                ALOGD("  %s", buf);
+                foundv4 = 1;
+            } else if (current->ai_addr->sa_family == AF_INET6) {
+                inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
+                        buf, sizeof(buf));
+                ALOGD("  %s", buf);
+                foundv6 = 1;
+            }
+            current = current->ai_next;
+        }
+
+        freeaddrinfo(answer);
+        answer = NULL;
+        if (foundv4 == 1 || foundv6 != 1) {
+            ALOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
+            return JNI_FALSE;
+        }
+    }
+
+    // getnameinfo
+    struct sockaddr_in sa4;
+    sa4.sin_family = AF_INET;
+    sa4.sin_port = 0;
+    inet_pton(AF_INET, "173.252.110.27", &(sa4.sin_addr));
+
+    struct sockaddr_in6 sa6;
+    sa6.sin6_family = AF_INET6;
+    sa6.sin6_port = 0;
+    sa6.sin6_flowinfo = 0;
+    sa6.sin6_scope_id = 0;
+    inet_pton(AF_INET6, "2001:4860:4001:802::1008", &(sa6.sin6_addr));
+
+    char buf[NI_MAXHOST];
+    int flags = NI_NAMEREQD;
+
+    res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags);
+    if (res != 0) {
+        ALOGD("getnameinfo(173.252.110.27 (facebook) ) gave error %d (%s)", res, gai_strerror(res));
+        return JNI_FALSE;
+    }
+    if (strstr(buf, "facebook.com") == NULL) {
+        ALOGD("getnameinfo(173.252.110.27 (facebook) ) didn't return facebook.com: %s", buf);
+        return JNI_FALSE;
+    }
+
+    memset(buf, sizeof(buf), 0);
+    res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf),
+            NULL, 0, flags);
+    if (res != 0) {
+        ALOGD("getnameinfo(2a03:2880:2110:df01:face:b00c::8 (facebook) ) gave error %d (%s)",
+                res, gai_strerror(res));
+        return JNI_FALSE;
+    }
+    if (strstr(buf, "1e100.net") == NULL) {
+        ALOGD("getnameinfo(2a03:2880:2110:df01:face:b00c::8) didn't return facebook.com: %s", buf);
+        return JNI_FALSE;
+    }
+
+    // gethostbyname
+    struct hostent *my_hostent = gethostbyname("www.mit.edu");
+    if (my_hostent == NULL) {
+        ALOGD("gethostbyname(www.mit.edu) gave null response");
+        return JNI_FALSE;
+    }
+    if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) {
+        ALOGD("gethostbyname(www.mit.edu) gave 0 addresses");
+        return JNI_FALSE;
+    }
+    {
+        char **current = my_hostent->h_addr_list;
+        while (*current != NULL) {
+            char buf[256];
+            inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf));
+            ALOGD("gethostbyname(www.mit.edu) gave %s", buf);
+            current++;
+        }
+    }
+
+    // gethostbyaddr
+    char addr6[16];
+    inet_pton(AF_INET6, "2001:4b10:bbc::2", addr6);
+    my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6);
+    if (my_hostent == NULL) {
+        ALOGD("gethostbyaddr(2001:4b10:bbc::2 (bbc) ) gave null response");
+        return JNI_FALSE;
+    }
+    ALOGD("gethostbyaddr(2001:4b10:bbc::2 (bbc) ) gave %s for name",
+    my_hostent->h_name ? my_hostent->h_name : "null");
+    if (my_hostent->h_name == NULL) return JNI_FALSE;
+    return JNI_TRUE;
+}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 4fa69a8..d4bff12 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -23,6 +23,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
+import android.net.NetworkConfig;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
@@ -30,7 +31,10 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -51,6 +55,9 @@
     private ConnectivityManager mCm;
     private WifiManager mWifiManager;
     private PackageManager mPackageManager;
+    private final HashMap<Integer, NetworkConfig> mNetworks =
+            new HashMap<Integer, NetworkConfig>();
+    private final List<Integer>mProtectedNetworks = new ArrayList<Integer>();
 
     @Override
     protected void setUp() throws Exception {
@@ -58,45 +65,124 @@
         mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         mPackageManager = getContext().getPackageManager();
-    }
 
-    public void testGetNetworkInfo() {
-        assertTrue(mCm.getAllNetworkInfo().length >= MIN_NUM_NETWORK_TYPES);
-        NetworkInfo ni = mCm.getNetworkInfo(TYPE_WIFI);
-        if (ni != null) {
-            State state = ni.getState();
-            assertTrue(State.UNKNOWN.ordinal() >= state.ordinal()
-                       && state.ordinal() >= State.CONNECTING.ordinal());
-            DetailedState ds = ni.getDetailedState();
-            assertTrue(DetailedState.FAILED.ordinal() >= ds.ordinal()
-                       && ds.ordinal() >= DetailedState.IDLE.ordinal());
+        String[] naStrings = getContext().getResources().getStringArray(
+                com.android.internal.R.array.networkAttributes);
+        for (String naString : naStrings) {
+            try {
+                NetworkConfig n = new NetworkConfig(naString);
+                mNetworks.put(n.type, n);
+            } catch (Exception e) {}
         }
-        ni = mCm.getNetworkInfo(TYPE_MOBILE);
-        if (ni != null) {
-            State state = ni.getState();
-            assertTrue(State.UNKNOWN.ordinal() >= state.ordinal()
-                    && state.ordinal() >= State.CONNECTING.ordinal());
-            DetailedState ds = ni.getDetailedState();
-            assertTrue(DetailedState.FAILED.ordinal() >= ds.ordinal()
-                    && ds.ordinal() >= DetailedState.IDLE.ordinal());
+
+        int[] protectedNetworks = getContext().getResources().getIntArray(
+                com.android.internal.R.array.config_protectedNetworks);
+        for (int p : protectedNetworks) {
+            mProtectedNetworks.add(p);
         }
-        ni = mCm.getNetworkInfo(-1);
-        assertNull(ni);
     }
 
     public void testIsNetworkTypeValid() {
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_MMS));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_SUPL));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_DUN));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_HIPRI));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIMAX));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_BLUETOOTH));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_DUMMY));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_ETHERNET));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_FOTA));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IMS));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_CBS));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI_P2P));
+        assertFalse(mCm.isNetworkTypeValid(-1));
+        assertTrue(mCm.isNetworkTypeValid(0));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE));
+        assertFalse(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE+1));
 
         NetworkInfo[] ni = mCm.getAllNetworkInfo();
 
-        for (NetworkInfo n : ni) {
+        for (NetworkInfo n: ni) {
             assertTrue(ConnectivityManager.isNetworkTypeValid(n.getType()));
         }
-        assertFalse(ConnectivityManager.isNetworkTypeValid(-1));
+
+    }
+
+    public void testSetNetworkPreference() {
+        // verify swtiching between two default networks - need to connectable networks though
+        // could use test and whatever the current active network is
+        int originalPref = mCm.getNetworkPreference();
+        int currentPref = originalPref;
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
+            mCm.setNetworkPreference(type);
+            NetworkConfig c = mNetworks.get(type);
+            boolean expectWorked = (c != null && c.isDefault());
+            int totalSleep = 0;
+            int foundType = ConnectivityManager.TYPE_NONE;
+            while (totalSleep < 1000) {
+                try {
+                    Thread.currentThread().sleep(100);
+                } catch (InterruptedException e) {}
+                totalSleep += 100;
+                foundType = mCm.getNetworkPreference();
+                if (currentPref != foundType) break;
+            }
+            if (expectWorked) {
+                assertTrue("We should have been able to switch prefered type " + type,
+                        foundType == type);
+            } else {
+                assertTrue("We should not have been able to switch type " + type,
+                        foundType != type);
+            }
+            currentPref = foundType;
+        }
+        mCm.setNetworkPreference(originalPref);
+    }
+
+    public void testGetActiveNetworkInfo() {
+        NetworkInfo ni = mCm.getActiveNetworkInfo();
+
+        assertTrue("You must have an active network connection to complete CTS", ni != null);
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType()));
+        assertTrue(ni.getState() == State.CONNECTED);
+    }
+
+    public void testGetNetworkInfo() {
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
+            if (isSupported(type)) {
+                NetworkInfo ni = mCm.getNetworkInfo(type);
+                assertTrue("Info shouldn't be null for " + type, ni != null);
+                State state = ni.getState();
+                assertTrue("Bad state for " + type, State.UNKNOWN.ordinal() >= state.ordinal()
+                           && state.ordinal() >= State.CONNECTING.ordinal());
+                DetailedState ds = ni.getDetailedState();
+                assertTrue("Bad detailed state for " + type,
+                           DetailedState.FAILED.ordinal() >= ds.ordinal()
+                           && ds.ordinal() >= DetailedState.IDLE.ordinal());
+            } else {
+                assertNull("Info should be null for " + type, mCm.getNetworkInfo(type));
+            }
+        }
     }
 
     public void testGetAllNetworkInfo() {
         NetworkInfo[] ni = mCm.getAllNetworkInfo();
         assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES);
+        for (int type = 0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            int desiredFoundCount = (isSupported(type) ? 1 : 0);
+            int foundCount = 0;
+            for (NetworkInfo i : ni) {
+                if (i.getType() == type) foundCount++;
+            }
+            if (foundCount != desiredFoundCount) {
+                Log.e(TAG, "failure in testGetAllNetworkInfo.  Dump of returned NetworkInfos:");
+                for (NetworkInfo networkInfo : ni) Log.e(TAG, "  " + networkInfo);
+            }
+            assertTrue("Unexpected foundCount of " + foundCount + " for type " + type,
+                    foundCount == desiredFoundCount);
+        }
     }
 
     public void testStartUsingNetworkFeature() {
@@ -130,35 +216,46 @@
         }
     }
 
-    public void testRequestRouteToHost() {
-        Set<Integer> exceptionFreeTypes = new HashSet<Integer>();
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_BLUETOOTH);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_ETHERNET);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_DUN);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_HIPRI);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_MMS);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_SUPL);
+    private boolean isSupported(int networkType) {
+        return mNetworks.containsKey(networkType);
+    }
 
-        NetworkInfo[] ni = mCm.getAllNetworkInfo();
-        for (NetworkInfo n : ni) {
-            if (n.isConnected() && exceptionFreeTypes.contains(n.getType())) {
-                assertTrue("Network type: " + n.getType(), mCm.requestRouteToHost(n.getType(),
-                        HOST_ADDRESS));
+    // true if only the system can turn it on
+    private boolean isNetworkProtected(int networkType) {
+        return mProtectedNetworks.contains(networkType);
+    }
+
+    public void testIsNetworkSupported() {
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            boolean supported = mCm.isNetworkSupported(type);
+            if (isSupported(type)) {
+                assertTrue(supported);
+            } else {
+                assertFalse(supported);
             }
         }
+    }
+
+    public void testRequestRouteToHost() {
+        for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            NetworkInfo ni = mCm.getNetworkInfo(type);
+            boolean expectToWork = isSupported(type) && !isNetworkProtected(type) &&
+                    ni != null && ni.isConnected();
+
+            try {
+                assertTrue("Network type " + type,
+                        mCm.requestRouteToHost(type, HOST_ADDRESS) == expectToWork);
+            } catch (Exception e) {
+                Log.d(TAG, "got exception in requestRouteToHost for type " + type);
+                assertFalse("Exception received for type " + type, expectToWork);
+            }
+
+            //TODO verify route table
+        }
 
         assertFalse(mCm.requestRouteToHost(-1, HOST_ADDRESS));
     }
 
-    public void testGetActiveNetworkInfo() {
-        NetworkInfo ni = mCm.getActiveNetworkInfo();
-
-        if (ni != null) {
-            assertTrue(ni.getType() >= 0);
-        }
-    }
-
     public void testTest() {
         mCm.getBackgroundDataSetting();
     }
@@ -197,12 +294,16 @@
 
             assertTrue("Couldn't requestRouteToHost using HIPRI.",
                     mCm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, HOST_ADDRESS));
-
+            // TODO check dns selection
+            // TODO check routes
         } catch (InterruptedException e) {
             fail("Broadcast receiver waiting for ConnectivityManager interrupted.");
         } finally {
             mCm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                     FEATURE_ENABLE_HIPRI);
+            // TODO wait for HIPRI to go
+            // TODO check dns selection
+            // TODO check routes
             if (!isWifiConnected) {
                 mWifiManager.setWifiEnabled(false);
             }
diff --git a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java b/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
index a5bbd98..180d259 100644
--- a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
+++ b/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
@@ -16,7 +16,6 @@
 
 package android.net.cts;
 
-
 import android.net.TrafficStats;
 import android.os.Process;
 import android.test.AndroidTestCase;
@@ -26,35 +25,73 @@
 import java.io.OutputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public class TrafficStatsTest extends AndroidTestCase {
-    public void testGetMobileStats() {
+    public void testValidMobileStats() {
         // We can't assume a mobile network is even present in this test, so
         // we simply assert that a valid value is returned.
 
-        assertTrue(TrafficStats.getMobileTxPackets() == TrafficStats.UNSUPPORTED ||
-                   TrafficStats.getMobileTxPackets() >= 0);
-        assertTrue(TrafficStats.getMobileRxPackets() == TrafficStats.UNSUPPORTED ||
-                   TrafficStats.getMobileRxPackets() >= 0);
-        assertTrue(TrafficStats.getMobileTxBytes() == TrafficStats.UNSUPPORTED ||
-                   TrafficStats.getMobileTxBytes() >= 0);
-        assertTrue(TrafficStats.getMobileRxBytes() == TrafficStats.UNSUPPORTED ||
-                   TrafficStats.getMobileRxBytes() >= 0);
+        assertTrue(TrafficStats.getMobileTxPackets() >= 0);
+        assertTrue(TrafficStats.getMobileRxPackets() >= 0);
+        assertTrue(TrafficStats.getMobileTxBytes() >= 0);
+        assertTrue(TrafficStats.getMobileRxBytes() >= 0);
+    }
+
+    public void testValidTotalStats() {
+        assertTrue(TrafficStats.getTotalTxPackets() >= 0);
+        assertTrue(TrafficStats.getTotalRxPackets() >= 0);
+        assertTrue(TrafficStats.getTotalTxBytes() >= 0);
+        assertTrue(TrafficStats.getTotalRxBytes() >= 0);
+    }
+
+    public void testThreadStatsTag() throws Exception {
+        TrafficStats.setThreadStatsTag(0xf00d);
+        assertTrue("Tag didn't stick", TrafficStats.getThreadStatsTag() == 0xf00d);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        new Thread("TrafficStatsTest.testThreadStatsTag") {
+            @Override
+            public void run() {
+                assertTrue("Tag leaked", TrafficStats.getThreadStatsTag() != 0xf00d);
+                TrafficStats.setThreadStatsTag(0xcafe);
+                assertTrue("Tag didn't stick", TrafficStats.getThreadStatsTag() == 0xcafe);
+                latch.countDown();
+            }
+        }.start();
+
+        latch.await(5, TimeUnit.SECONDS);
+        assertTrue("Tag lost", TrafficStats.getThreadStatsTag() == 0xf00d);
+
+        TrafficStats.clearThreadStatsTag();
+        assertTrue("Tag not cleared", TrafficStats.getThreadStatsTag() != 0xf00d);
+    }
+
+    long tcpPacketToIpBytes(long packetCount, long bytes) {
+        // ip header + tcp header + data.
+        // Tcp header is mostly 32. Syn has different tcp options -> 40. Don't care.
+        return packetCount * (20 + 32 + bytes);
     }
 
     public void testTrafficStatsForLocalhost() throws IOException {
-        long mobileTxPacketsBefore = TrafficStats.getTotalTxPackets();
-        long mobileRxPacketsBefore = TrafficStats.getTotalRxPackets();
-        long mobileTxBytesBefore = TrafficStats.getTotalTxBytes();
-        long mobileRxBytesBefore = TrafficStats.getTotalRxBytes();
+        long mobileTxPacketsBefore = TrafficStats.getMobileTxPackets();
+        long mobileRxPacketsBefore = TrafficStats.getMobileRxPackets();
+        long mobileTxBytesBefore = TrafficStats.getMobileTxBytes();
+        long mobileRxBytesBefore = TrafficStats.getMobileRxBytes();
         long totalTxPacketsBefore = TrafficStats.getTotalTxPackets();
         long totalRxPacketsBefore = TrafficStats.getTotalRxPackets();
         long totalTxBytesBefore = TrafficStats.getTotalTxBytes();
         long totalRxBytesBefore = TrafficStats.getTotalRxBytes();
         long uidTxBytesBefore = TrafficStats.getUidTxBytes(Process.myUid());
         long uidRxBytesBefore = TrafficStats.getUidRxBytes(Process.myUid());
+        long uidTxPacketsBefore = TrafficStats.getUidTxPackets(Process.myUid());
+        long uidRxPacketsBefore = TrafficStats.getUidRxPackets(Process.myUid());
 
         // Transfer 1MB of data across an explicitly localhost socket.
+        final int byteCount = 1024;
+        final int packetCount = 1024;
 
         final ServerSocket server = new ServerSocket(0);
         new Thread("TrafficStatsTest.testTrafficStatsForLocalhost") {
@@ -62,9 +99,15 @@
             public void run() {
                 try {
                     Socket socket = new Socket("localhost", server.getLocalPort());
+                    // Make sure that each write()+flush() turns into a packet:
+                    // disable Nagle.
+                    socket.setTcpNoDelay(true);
                     OutputStream out = socket.getOutputStream();
-                    byte[] buf = new byte[1024];
-                    for (int i = 0; i < 1024; i++) out.write(buf);
+                    byte[] buf = new byte[byteCount];
+                    for (int i = 0; i < packetCount; i++) {
+                        out.write(buf);
+                        out.flush();
+                    }
                     out.close();
                     socket.close();
                 } catch (IOException e) {
@@ -75,9 +118,9 @@
         try {
             Socket socket = server.accept();
             InputStream in = socket.getInputStream();
-            byte[] buf = new byte[1024];
+            byte[] buf = new byte[byteCount];
             int read = 0;
-            while (read < 1048576) {
+            while (read < byteCount * packetCount) {
                 int n = in.read(buf);
                 assertTrue("Unexpected EOF", n > 0);
                 read += n;
@@ -92,50 +135,76 @@
         } catch (InterruptedException e) {
         }
 
-        long mobileTxPacketsAfter = TrafficStats.getTotalTxPackets();
-        long mobileRxPacketsAfter = TrafficStats.getTotalRxPackets();
-        long mobileTxBytesAfter = TrafficStats.getTotalTxBytes();
-        long mobileRxBytesAfter = TrafficStats.getTotalRxBytes();
+        long mobileTxPacketsAfter = TrafficStats.getMobileTxPackets();
+        long mobileRxPacketsAfter = TrafficStats.getMobileRxPackets();
+        long mobileTxBytesAfter = TrafficStats.getMobileTxBytes();
+        long mobileRxBytesAfter = TrafficStats.getMobileRxBytes();
         long totalTxPacketsAfter = TrafficStats.getTotalTxPackets();
         long totalRxPacketsAfter = TrafficStats.getTotalRxPackets();
         long totalTxBytesAfter = TrafficStats.getTotalTxBytes();
         long totalRxBytesAfter = TrafficStats.getTotalRxBytes();
         long uidTxBytesAfter = TrafficStats.getUidTxBytes(Process.myUid());
         long uidRxBytesAfter = TrafficStats.getUidRxBytes(Process.myUid());
-
-        // Localhost traffic should *not* count against mobile or total stats.
-        // There might be some other traffic, but nowhere near 1MB.
-
-        assertTrue("mtxp: " + mobileTxPacketsBefore + " -> " + mobileTxPacketsAfter,
-               mobileTxPacketsAfter >= mobileTxPacketsBefore &&
-               mobileTxPacketsAfter <= mobileTxPacketsBefore + 500);
-        assertTrue("mrxp: " + mobileRxPacketsBefore + " -> " + mobileRxPacketsAfter,
-               mobileRxPacketsAfter >= mobileRxPacketsBefore &&
-               mobileRxPacketsAfter <= mobileRxPacketsBefore + 500);
-        assertTrue("mtxb: " + mobileTxBytesBefore + " -> " + mobileTxBytesAfter,
-               mobileTxBytesAfter >= mobileTxBytesBefore &&
-               mobileTxBytesAfter <= mobileTxBytesBefore + 200000);
-        assertTrue("mrxb: " + mobileRxBytesBefore + " -> " + mobileRxBytesAfter,
-               mobileRxBytesAfter >= mobileRxBytesBefore &&
-               mobileRxBytesAfter <= mobileRxBytesBefore + 200000);
-
-        assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter,
-               totalTxPacketsAfter >= totalTxPacketsBefore &&
-               totalTxPacketsAfter <= totalTxPacketsBefore + 500);
-        assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter,
-               totalRxPacketsAfter >= totalRxPacketsBefore &&
-               totalRxPacketsAfter <= totalRxPacketsBefore + 500);
-        assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter,
-               totalTxBytesAfter >= totalTxBytesBefore &&
-               totalTxBytesAfter <= totalTxBytesBefore + 200000);
-        assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter,
-               totalRxBytesAfter >= totalRxBytesBefore &&
-               totalRxBytesAfter <= totalRxBytesBefore + 200000);
+        long uidTxPacketsAfter = TrafficStats.getUidTxPackets(Process.myUid());
+        long uidRxPacketsAfter = TrafficStats.getUidRxPackets(Process.myUid());
+        long uidTxDeltaBytes = uidTxBytesAfter - uidTxBytesBefore;
+        long uidTxDeltaPackets = uidTxPacketsAfter - uidTxPacketsBefore;
+        long uidRxDeltaBytes = uidRxBytesAfter - uidRxBytesBefore;
+        long uidRxDeltaPackets = uidRxPacketsAfter - uidRxPacketsBefore;
 
         // Localhost traffic *does* count against per-UID stats.
-        assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter,
-               uidTxBytesAfter >= uidTxBytesBefore + 1048576);
-        assertTrue("uidrxb: " + uidRxBytesBefore + " -> " + uidRxBytesAfter,
-               uidRxBytesAfter >= uidRxBytesBefore + 1048576);
+        /*
+         * Calculations:
+         *  - bytes
+         *   bytes is approx: packets * data + packets * acks;
+         *   but sometimes there are less acks than packets, so we set a lower
+         *   limit of 1 ack.
+         *  - setup/teardown
+         *   + 7 approx.: syn, syn-ack, ack, fin-ack, ack, fin-ack, ack;
+         *   but sometimes the last find-acks just vanish, so we set a lower limit of +5.
+         */
+        assertTrue("uidtxp: " + uidTxPacketsBefore + " -> " + uidTxPacketsAfter + " delta=" + uidTxDeltaPackets,
+            uidTxDeltaPackets >= packetCount + 5 &&
+            uidTxDeltaPackets <= packetCount + packetCount + 7);
+        assertTrue("uidrxp: " + uidRxPacketsBefore + " -> " + uidRxPacketsAfter + " delta=" + uidRxDeltaPackets,
+            uidRxDeltaPackets >= packetCount + 5 &&
+            uidRxDeltaPackets <= packetCount + packetCount + 7);
+        assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter + " delta=" + uidTxDeltaBytes,
+            uidTxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(5, 0) &&
+            uidTxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + 7, 0));
+        assertTrue("uidrxb: " + uidRxBytesBefore + " -> " + uidRxBytesAfter + " delta=" + uidRxDeltaBytes,
+            uidRxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(5, 0) &&
+            uidRxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + 7, 0));
+
+        // Localhost traffic *does* count against total stats.
+        // Fudge by 132 packets of 1500 bytes not related to the test.
+        assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter,
+            totalTxPacketsAfter >= totalTxPacketsBefore + uidTxDeltaPackets &&
+            totalTxPacketsAfter <= totalTxPacketsBefore + uidTxDeltaPackets + 132);
+        assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter,
+            totalRxPacketsAfter >= totalRxPacketsBefore + uidRxDeltaPackets &&
+            totalRxPacketsAfter <= totalRxPacketsBefore + uidRxDeltaPackets + 132);
+        assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter,
+            totalTxBytesAfter >= totalTxBytesBefore + uidTxDeltaBytes &&
+            totalTxBytesAfter <= totalTxBytesBefore + uidTxDeltaBytes + 132 * 1500);
+        assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter,
+            totalRxBytesAfter >= totalRxBytesBefore + uidRxDeltaBytes &&
+            totalRxBytesAfter <= totalRxBytesBefore + uidRxDeltaBytes + 132 * 1500);
+
+        // Localhost traffic should *not* count against mobile stats,
+        // There might be some other traffic, but nowhere near 1MB.
+        assertTrue("mtxp: " + mobileTxPacketsBefore + " -> " + mobileTxPacketsAfter,
+            mobileTxPacketsAfter >= mobileTxPacketsBefore &&
+            mobileTxPacketsAfter <= mobileTxPacketsBefore + 500);
+        assertTrue("mrxp: " + mobileRxPacketsBefore + " -> " + mobileRxPacketsAfter,
+            mobileRxPacketsAfter >= mobileRxPacketsBefore &&
+            mobileRxPacketsAfter <= mobileRxPacketsBefore + 500);
+        assertTrue("mtxb: " + mobileTxBytesBefore + " -> " + mobileTxBytesAfter,
+            mobileTxBytesAfter >= mobileTxBytesBefore &&
+            mobileTxBytesAfter <= mobileTxBytesBefore + 200000);
+        assertTrue("mrxb: " + mobileRxBytesBefore + " -> " + mobileRxBytesAfter,
+            mobileRxBytesAfter >= mobileRxBytesBefore &&
+            mobileRxBytesAfter <= mobileRxBytesBefore + 200000);
+
     }
 }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
new file mode 100644
index 0000000..58298d5
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.cts;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiEnterpriseConfig.Eap;
+import android.net.wifi.WifiEnterpriseConfig.Phase2;
+import android.net.wifi.WifiManager;
+import android.test.AndroidTestCase;
+
+public class WifiEnterpriseConfigTest extends AndroidTestCase {
+    private  WifiManager mWifiManager;
+
+    private static final String SSID = "\"TestSSID\"";
+    private static final String IDENTITY = "identity";
+    private static final String PASSWORD = "password";
+    private static final String SUBJECT_MATCH = "subjectmatch";
+    private static final String ANON_IDENTITY = "anonidentity";
+    private static final int ENABLE_DELAY = 10000;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mWifiManager = (WifiManager) mContext
+                .getSystemService(Context.WIFI_SERVICE);
+        assertNotNull(mWifiManager);
+        mWifiManager.setWifiEnabled(true);
+        Thread.sleep(ENABLE_DELAY);
+        assertTrue(mWifiManager.isWifiEnabled());
+    }
+
+    public void testSettersAndGetters() {
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+        assertTrue(config.getEapMethod() == Eap.NONE);
+        config.setEapMethod(Eap.PEAP);
+        assertTrue(config.getEapMethod() == Eap.PEAP);
+        config.setEapMethod(Eap.PWD);
+        assertTrue(config.getEapMethod() == Eap.PWD);
+        config.setEapMethod(Eap.TLS);
+        assertTrue(config.getEapMethod() == Eap.TLS);
+        config.setEapMethod(Eap.TTLS);
+        assertTrue(config.getEapMethod() == Eap.TTLS);
+        assertTrue(config.getPhase2Method() == Phase2.NONE);
+        config.setPhase2Method(Phase2.PAP);
+        assertTrue(config.getPhase2Method() == Phase2.PAP);
+        config.setPhase2Method(Phase2.MSCHAP);
+        assertTrue(config.getPhase2Method() == Phase2.MSCHAP);
+        config.setPhase2Method(Phase2.MSCHAPV2);
+        assertTrue(config.getPhase2Method() == Phase2.MSCHAPV2);
+        config.setPhase2Method(Phase2.GTC);
+        assertTrue(config.getPhase2Method() == Phase2.GTC);
+        config.setIdentity(IDENTITY);
+        assertTrue(config.getIdentity().equals(IDENTITY));
+        config.setAnonymousIdentity(ANON_IDENTITY);
+        assertTrue(config.getAnonymousIdentity().equals(ANON_IDENTITY));
+        config.setPassword(PASSWORD);
+        assertTrue(config.getPassword().equals(PASSWORD));
+        config.setCaCertificate(null);
+        config.setClientKeyEntry(null, null);
+        config.setSubjectMatch(SUBJECT_MATCH);
+        assertTrue(config.getSubjectMatch().equals(SUBJECT_MATCH));
+    }
+
+    public void testAddEapNetwork() {
+        WifiConfiguration config = new WifiConfiguration();
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(Eap.PWD);
+        enterpriseConfig.setIdentity(IDENTITY);
+        enterpriseConfig.setPassword(PASSWORD);
+        config.SSID = SSID;
+        config.enterpriseConfig = enterpriseConfig;
+
+        int netId = mWifiManager.addNetwork(config);
+        assertTrue(doesSsidExist(SSID));
+        mWifiManager.removeNetwork(netId);
+        assertFalse(doesSsidExist(SSID));
+    }
+
+    private boolean doesSsidExist(String ssid) {
+        for (final WifiConfiguration w : mWifiManager.getConfiguredNetworks()) {
+            if (w.SSID.equals(ssid))
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
index 16dc57d..8719b6b 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -122,7 +122,13 @@
         assertNotNull(wifiInfo.toString());
         SupplicantState.isValidState(wifiInfo.getSupplicantState());
         WifiInfo.getDetailedStateOf(SupplicantState.DISCONNECTED);
-        wifiInfo.getSSID();
+        String ssid = wifiInfo.getSSID();
+        if (ssid.startsWith("0x") == false) {
+            // Non-hex string should be quoted
+            assertTrue(ssid.charAt(0) == '"');
+            assertTrue(ssid.charAt(ssid.length() - 1) == '"');
+        }
+
         wifiInfo.getBSSID();
         wifiInfo.getIpAddress();
         wifiInfo.getLinkSpeed();
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
index 283f63b..2580dbe 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -233,7 +233,7 @@
         startScan();
         setWifiEnabled(false);
         Thread.sleep(DURATION);
-        assertFalse(mWifiManager.pingSupplicant());
+        assertTrue(mWifiManager.pingSupplicant() == mWifiManager.isScanAlwaysAvailable());
         final String TAG = "Test";
         assertNotNull(mWifiManager.createWifiLock(TAG));
         assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG));