1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.cuttlefish.wifi.tests;
17 
18 import android.content.Context;
19 import android.net.ConnectivityManager;
20 import android.net.Network;
21 import android.net.NetworkInfo;
22 import android.net.wifi.SupplicantState;
23 import android.net.wifi.WifiConfiguration;
24 import android.net.wifi.WifiInfo;
25 import android.net.wifi.WifiManager;
26 import android.util.Log;
27 
28 import androidx.test.InstrumentationRegistry;
29 import androidx.test.core.app.ApplicationProvider;
30 
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.junit.runners.JUnit4;
36 
37 import java.net.InetSocketAddress;
38 import java.net.Socket;
39 import java.net.SocketTimeoutException;
40 import java.util.List;
41 
42 /**
43  * Tests used to validate E2E WIFI functionality.
44  */
45 @RunWith(JUnit4.class)
46 public class WifiE2eTests {
47     private static final String TAG = "WifiE2eTests";
48     private Context mContext;
49     private WifiManager mWifiManager;
50     private ConnectivityManager mConnManager;
51 
52     @Before
setUp()53     public void setUp() throws Exception {
54         mContext = ApplicationProvider.getApplicationContext();
55         mWifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
56         mConnManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
57     }
58 
59 
60     @SuppressWarnings("unused")
enableWifi()61     private void enableWifi() throws InterruptedException {
62         Log.i(TAG, "Enabling WIFI...");
63         mWifiManager.setWifiEnabled(true);
64         while (!mWifiManager.isWifiEnabled()) {
65             Log.i(TAG, "Waiting for WIFI to be enabled...");
66             Thread.sleep(1000);
67         }
68     }
69 
70 
71     @SuppressWarnings("unused")
disableWifi()72     private void disableWifi() throws InterruptedException {
73         Log.i(TAG, "Disabling WIFI...");
74 
75         mWifiManager.setWifiEnabled(false);
76         while (mWifiManager.isWifiEnabled()) {
77             Log.i(TAG, "Waiting for WIFI to be disabled...");
78             Thread.sleep(1000);
79         }
80     }
81 
82 
waitForSupplicantState(SupplicantState... expectedStates)83     private void waitForSupplicantState(SupplicantState... expectedStates)
84             throws InterruptedException {
85         while (true) {
86             WifiInfo info = mWifiManager.getConnectionInfo();
87             SupplicantState currentState = info.getSupplicantState();
88 
89             Log.i(TAG, "WIFI State: " + currentState);
90             for (SupplicantState state : expectedStates) {
91                 if (currentState == state) {
92                     Log.i(TAG, "WIFI is now in expected state.");
93                     return;
94                 }
95             }
96 
97             Thread.sleep(1000);
98         }
99     }
100 
101 
enableNetwork(String SSID)102     private void enableNetwork(String SSID) {
103         WifiConfiguration conf = new WifiConfiguration();
104         conf.SSID = SSID;
105         conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
106         int networkId = mWifiManager.addNetwork(conf);
107         Assert.assertTrue(networkId >= 0);
108         mWifiManager.enableNetwork(networkId, false);
109     }
110 
111 
112     /**
113      * Initialize wifi, erase all settings.
114      */
115     @Test(timeout = 10 * 1000)
testWifiInitialization()116     public void testWifiInitialization() throws Exception {
117         enableWifi();
118 
119         List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
120         Assert.assertNotNull(configs);
121         for (WifiConfiguration config : configs) {
122             Log.i(TAG, "Removing network " + config.networkId + ": " + config.SSID);
123             mWifiManager.disableNetwork(config.networkId);
124             mWifiManager.removeNetwork(config.networkId);
125         }
126         configs = mWifiManager.getConfiguredNetworks();
127         Assert.assertEquals(0, configs.size());
128 
129         waitForSupplicantState(
130                 SupplicantState.INACTIVE,
131                 SupplicantState.DISCONNECTED,
132                 SupplicantState.SCANNING);
133 
134         disableWifi();
135     }
136 
137 
138     /**
139      * Verify that WIFI stack is able to get up and connect to network in
140      * 60 seconds.
141      */
142     @Test(timeout = 60 * 1000)
testWifiConnects()143     public void testWifiConnects() throws Exception {
144         // 1. Make sure we start with WIFI disabled.
145         // It could be, that WIFI is currently disabled anyway.
146         // Let's make sure that's the case.
147         disableWifi();
148 
149         // 2. Wait until stack is up.
150         enableWifi();
151 
152         // 3. Configure WIFI:
153         //    - Add network,
154         //    - Enable network,
155         //    - Scan for network
156         Log.i(TAG, "Configuring WIFI...");
157         enableNetwork("\"VirtWifi\"");
158         enableNetwork("\"AndroidWifi\"");
159         mWifiManager.startScan();
160 
161         // 4. Wait until connected.
162         Log.i(TAG, "Waiting for connectivity...");
163         waitForSupplicantState(SupplicantState.COMPLETED);
164 
165         // 5. Wait until WIFI is current network.
166         while (true) {
167             NetworkInfo net = mConnManager.getActiveNetworkInfo();
168             if (net != null && net.getType() == ConnectivityManager.TYPE_WIFI) break;
169 
170             Log.i(TAG, "Waiting for WIFI to become primary network for DATA.");
171 
172             Thread.sleep(1000);
173         }
174 
175         // 6. Bind process to WIFI network. This should allow us to verify network is functional.
176         Network net = mConnManager.getActiveNetwork();
177         Assert.assertNotNull(net);
178         Assert.assertTrue(mConnManager.bindProcessToNetwork(net));
179 
180         // 7. Open connection to Google public DNS server
181         InetSocketAddress addr = new InetSocketAddress("8.8.8.8", 53);
182         while (true) {
183             try (Socket s = new Socket()) {
184                 Log.d(TAG, "Testing socket connection to 8.8.8.8:53...");
185                 s.connect(addr, 5000); // use a socket connection timeout of 5s
186                 Assert.assertTrue(
187                         "Failed to make socket connection to 8.8.8.8:53", s.isConnected());
188                 return;
189             } catch (SocketTimeoutException e) {
190                 Log.d(TAG, "Socket connection to 8.8.8.8:53 timed out (5s), retry...");
191             }
192         }
193     }
194 }
195