1 /* 2 * Copyright (C) 2015 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 17 package android.net.cts.legacy.api22; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.pm.PackageManager; 24 import android.net.ConnectivityManager; 25 import android.net.LinkAddress; 26 import android.net.LinkProperties; 27 import android.net.Network; 28 import android.net.NetworkInfo; 29 import android.net.wifi.WifiManager; 30 import android.os.ConditionVariable; 31 import android.test.AndroidTestCase; 32 import android.util.Log; 33 34 import java.net.DatagramSocket; 35 import java.net.Inet4Address; 36 import java.net.InetAddress; 37 import java.util.ArrayList; 38 import java.util.List; 39 40 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 41 import static android.net.ConnectivityManager.TYPE_MOBILE; 42 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; 43 import static android.net.ConnectivityManager.TYPE_VPN; 44 import static android.net.ConnectivityManager.TYPE_WIFI; 45 46 public class ConnectivityManagerLegacyTest extends AndroidTestCase { 47 private static final String TAG = ConnectivityManagerLegacyTest.class.getSimpleName(); 48 private static final String FEATURE_ENABLE_HIPRI = "enableHIPRI"; 49 private static final String HOST_ADDRESS1 = "192.0.2.1"; 50 private static final String HOST_ADDRESS2 = "192.0.2.2"; 51 private static final String HOST_ADDRESS3 = "192.0.2.3"; 52 53 // These are correct as of API level 22, which is what we target here. 54 private static final int APN_REQUEST_FAILED = 3; 55 private static final int MAX_NETWORK_TYPE = TYPE_VPN; 56 57 private ConnectivityManager mCm; 58 private WifiManager mWifiManager; 59 private PackageManager mPackageManager; 60 61 private final List<Integer>mProtectedNetworks = new ArrayList<Integer>(); 62 setUp()63 protected void setUp() throws Exception { 64 super.setUp(); 65 mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); 66 mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 67 mPackageManager = getContext().getPackageManager(); 68 69 // Get com.android.internal.R.array.config_protectedNetworks 70 int resId = getContext().getResources().getIdentifier("config_protectedNetworks", "array", "android"); 71 int[] protectedNetworks = getContext().getResources().getIntArray(resId); 72 for (int p : protectedNetworks) { 73 mProtectedNetworks.add(p); 74 } 75 } 76 77 // true if only the system can turn it on isNetworkProtected(int networkType)78 private boolean isNetworkProtected(int networkType) { 79 return mProtectedNetworks.contains(networkType); 80 } 81 ipv4AddrToInt(String addrString)82 private int ipv4AddrToInt(String addrString) throws Exception { 83 byte[] addr = ((Inet4Address) InetAddress.getByName(addrString)).getAddress(); 84 return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) | 85 ((addr[1] & 0xff) << 8) | (addr[0] & 0xff); 86 } 87 checkSourceAddress(String addrString, int type)88 private void checkSourceAddress(String addrString, int type) throws Exception { 89 DatagramSocket d = new DatagramSocket(); 90 d.connect(InetAddress.getByName(addrString), 7); 91 InetAddress localAddress = d.getLocalAddress(); 92 93 Network[] networks = mCm.getAllNetworks(); 94 for (int i = 0; i < networks.length; i++) { 95 NetworkInfo ni = mCm.getNetworkInfo(networks[i]); 96 if (ni != null && ni.getType() == type) { 97 LinkProperties lp = mCm.getLinkProperties(networks[i]); 98 for (LinkAddress address : lp.getLinkAddresses()) { 99 if (address.getAddress().equals(localAddress)) { 100 return; 101 } 102 } 103 } 104 } 105 fail("Local address " + localAddress + " not assigned to any network of type " + type); 106 } 107 108 /** Test that hipri can be brought up when Wifi is enabled. */ testStartUsingNetworkFeature_enableHipri()109 public void testStartUsingNetworkFeature_enableHipri() throws Exception { 110 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) 111 || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) { 112 // This test requires a mobile data connection and WiFi. 113 return; 114 } 115 116 // Make sure WiFi is connected to an access point. 117 connectToWifi(); 118 119 expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.CONNECTED, 120 new Runnable() { 121 public void run() { 122 int ret = mCm.startUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI); 123 assertTrue("Couldn't start using the HIPRI feature.", ret != -1); 124 } 125 }); 126 127 assertTrue("Couldn't requestRouteToHost using HIPRI.", 128 mCm.requestRouteToHost(TYPE_MOBILE_HIPRI, ipv4AddrToInt(HOST_ADDRESS1))); 129 130 try { Thread.sleep(1000); } catch(Exception e) {} 131 checkSourceAddress(HOST_ADDRESS1, TYPE_MOBILE); 132 checkSourceAddress(HOST_ADDRESS2, TYPE_WIFI); 133 134 // TODO check dns selection 135 136 expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.DISCONNECTED, 137 new Runnable() { 138 public void run() { 139 int ret = mCm.stopUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI); 140 assertTrue("Couldn't stop using the HIPRI feature.", ret != -1); 141 } 142 }); 143 144 145 // TODO check dns selection 146 disconnectFromWifi(); 147 } 148 testStartUsingNetworkFeature()149 public void testStartUsingNetworkFeature() { 150 151 final String invalidFeature = "invalidFeature"; 152 final String mmsFeature = "enableMMS"; 153 final int failureCode = -1; 154 final int wifiOnlyStartFailureCode = APN_REQUEST_FAILED; 155 final int wifiOnlyStopFailureCode = -1; 156 157 NetworkInfo ni = mCm.getNetworkInfo(TYPE_MOBILE); 158 if (ni != null) { 159 assertEquals(APN_REQUEST_FAILED, 160 mCm.startUsingNetworkFeature(TYPE_MOBILE, invalidFeature)); 161 assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE, invalidFeature)); 162 } else { 163 assertEquals(wifiOnlyStartFailureCode, mCm.startUsingNetworkFeature(TYPE_MOBILE, 164 invalidFeature)); 165 assertEquals(wifiOnlyStopFailureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE, 166 invalidFeature)); 167 } 168 169 ni = mCm.getNetworkInfo(TYPE_WIFI); 170 if (ni != null) { 171 // Should return failure because MMS is not supported on WIFI. 172 assertEquals(APN_REQUEST_FAILED, mCm.startUsingNetworkFeature(TYPE_WIFI, 173 mmsFeature)); 174 assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_WIFI, 175 mmsFeature)); 176 } 177 } 178 expectNetworkBroadcast(final int type, final NetworkInfo.State state, Runnable afterWhat)179 private void expectNetworkBroadcast(final int type, final NetworkInfo.State state, 180 Runnable afterWhat) { 181 final int TIMEOUT_MS = 30 * 1000; 182 final ConditionVariable var = new ConditionVariable(); 183 184 Log.d(TAG, "Waiting for " + state + " broadcast for type " + type); 185 BroadcastReceiver receiver = new BroadcastReceiver() { 186 public void onReceive(Context context, Intent intent) { 187 NetworkInfo ni = intent.getExtras() 188 .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO); 189 assertNotNull("CONNECTIVITY_ACTION with null EXTRA_NETWORK_INFO", ni); 190 if (ni.getType() == type && ni.getState().equals(state)) { 191 Log.d(TAG, "Received expected " + state + " broadcast for type " + type); 192 var.open(); 193 } 194 } 195 }; 196 IntentFilter filter = new IntentFilter(); 197 filter.addAction(CONNECTIVITY_ACTION); 198 mContext.registerReceiver(receiver, filter); 199 200 try { 201 afterWhat.run(); 202 final String msg = "Did not receive expected " + state + " broadcast for type " + type + 203 " after " + TIMEOUT_MS + " ms"; 204 assertTrue(msg, var.block(TIMEOUT_MS)); 205 } finally { 206 mContext.unregisterReceiver(receiver); 207 } 208 } 209 isWifiConnected()210 private boolean isWifiConnected() { 211 NetworkInfo ni = mCm.getNetworkInfo(TYPE_WIFI); 212 return ni != null && ni.isConnected(); 213 } 214 setWifiState(final boolean enabled)215 private void setWifiState(final boolean enabled) { 216 if (enabled != isWifiConnected()) { 217 final NetworkInfo.State desiredState = enabled ? 218 NetworkInfo.State.CONNECTED : 219 NetworkInfo.State.DISCONNECTED; 220 expectNetworkBroadcast(TYPE_WIFI, desiredState, new Runnable() { 221 public void run() { 222 mWifiManager.setWifiEnabled(enabled); 223 } 224 }); 225 } 226 } 227 connectToWifi()228 private void connectToWifi() { 229 setWifiState(true); 230 } 231 disconnectFromWifi()232 private void disconnectFromWifi() { 233 setWifiState(false); 234 } 235 isNetworkSupported(int networkType)236 private boolean isNetworkSupported(int networkType) { 237 return mCm.getNetworkInfo(networkType) != null; 238 } 239 testRequestRouteToHost()240 public void testRequestRouteToHost() throws Exception { 241 for (int type = -1 ; type <= MAX_NETWORK_TYPE; type++) { 242 NetworkInfo ni = mCm.getNetworkInfo(type); 243 boolean expectToWork = isNetworkSupported(type) && !isNetworkProtected(type) && 244 ni != null && ni.isConnected(); 245 246 try { 247 assertTrue("Network type " + type, 248 mCm.requestRouteToHost(type, ipv4AddrToInt(HOST_ADDRESS3)) == expectToWork); 249 } catch (Exception e) { 250 Log.d(TAG, "got exception in requestRouteToHost for type " + type); 251 assertFalse("Exception received for type " + type, expectToWork); 252 } 253 254 //TODO verify route table 255 } 256 257 assertFalse(mCm.requestRouteToHost(-1, ipv4AddrToInt(HOST_ADDRESS1))); 258 } 259 } 260