Merge "Change test to use set-mode cmd." into oc-dev
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 24871ca..83f087b 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -45,12 +45,15 @@
 
 import com.android.internal.telephony.PhoneConstants;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
+import java.util.Scanner;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -74,6 +77,17 @@
             "Host: " + TEST_HOST + "\r\n" +
             "Connection: keep-alive\r\n\r\n";
 
+    // Base path for IPv6 sysctls
+    private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+
+    // Expected values for MIN|MAX_PLEN.
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN = 48;
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN = 64;
+
+    // Expected values for RFC 7559 router soliciations.
+    // Maximum number of router solicitations to send. -1 means no limit.
+    private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
+
     // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
     private static final String NETWORK_CALLBACK_ACTION =
             "ConnectivityManagerTest.NetworkCallbackAction";
@@ -91,6 +105,7 @@
     private PackageManager mPackageManager;
     private final HashMap<Integer, NetworkConfig> mNetworks =
             new HashMap<Integer, NetworkConfig>();
+    boolean mWifiConnectAttempted;
 
     @Override
     protected void setUp() throws Exception {
@@ -99,6 +114,7 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mPackageManager = mContext.getPackageManager();
+        mWifiConnectAttempted = false;
 
         // Get com.android.internal.R.array.networkAttributes
         int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android");
@@ -116,6 +132,27 @@
         }
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        // Return WiFi to its original disabled state after tests that explicitly connect.
+        if (mWifiConnectAttempted) {
+            disconnectFromWifi(null);
+        }
+    }
+
+    /**
+     * Make sure WiFi is connected to an access point if it is not already. If
+     * WiFi is enabled as a result of this function, it will be disabled
+     * automatically in tearDown().
+     */
+    private Network ensureWifiConnected() {
+        if (mWifiManager.isWifiEnabled()) {
+            return getWifiNetwork();
+        }
+        mWifiConnectAttempted = true;
+        return connectToWifi();
+    }
+
     public void testIsNetworkTypeValid() {
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
@@ -298,14 +335,10 @@
         final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
         Network wifiNetwork = null;
 
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we should expect to get a network callback about availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -321,11 +354,6 @@
         } finally {
             mCm.unregisterNetworkCallback(callback);
             mCm.unregisterNetworkCallback(defaultTrackingCallback);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(wifiNetwork);
-            }
         }
     }
 
@@ -357,13 +385,8 @@
         // We will register for a WIFI network being available or lost.
         mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
-
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we expect to get the Intent delivered notifying of the availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -376,11 +399,6 @@
             mCm.unregisterNetworkCallback(pendingIntent);
             pendingIntent.cancel();
             mContext.unregisterReceiver(receiver);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(null);
-            }
         }
     }
 
@@ -761,4 +779,42 @@
             fail("No exception thrown when restricted network requested.");
         } catch (SecurityException expected) {}
     }
+
+    private Scanner makeWifiSysctlScanner(String key) throws FileNotFoundException {
+        Network network = ensureWifiConnected();
+        String iface = mCm.getLinkProperties(network).getInterfaceName();
+        String path = IPV6_SYSCTL_DIR + "/" + iface + "/" + key;
+        return new Scanner(new File(path));
+    }
+
+    /** Verify that accept_ra_rt_info_min_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMinPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_min_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN, s.nextInt());
+    }
+
+    /** Verify that accept_ra_rt_info_max_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMaxPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_max_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN, s.nextInt());
+    }
+
+    /** Verify that router_solicitations exists and is set to the expected value */
+    public void testRouterSolicitations() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitations");
+        assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, s.nextInt());
+    }
+
+    /** Verify that router_solicitation_max_interval exists and is in an acceptable interval */
+    public void testRouterSolicitationMaxInterval() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitation_max_interval");
+        int interval = s.nextInt();
+        // Verify we're in the interval [15 minutes, 60 minutes]. Lower values may adversely
+        // impact battery life and higher values can decrease the probability of detecting
+        // network changes.
+        final int lowerBoundSec = 15 * 60;
+        final int upperBoundSec = 60 * 60;
+        assertTrue(lowerBoundSec <= interval);
+        assertTrue(interval <= upperBoundSec);
+    }
 }