1 /* 2 * Copyright (C) 2012 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 com.android.server; 18 19 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 20 import static android.net.ConnectivityManager.TYPE_MOBILE; 21 import static android.net.ConnectivityManager.TYPE_WIFI; 22 import static android.net.ConnectivityManager.getNetworkTypeName; 23 import static android.net.NetworkStateTracker.EVENT_STATE_CHANGED; 24 import static org.mockito.Matchers.anyInt; 25 import static org.mockito.Matchers.eq; 26 import static org.mockito.Matchers.isA; 27 import static org.mockito.Mockito.doNothing; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.doThrow; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.reset; 32 import static org.mockito.Mockito.verify; 33 34 import android.content.Context; 35 import android.net.INetworkPolicyManager; 36 import android.net.INetworkStatsService; 37 import android.net.LinkProperties; 38 import android.net.NetworkConfig; 39 import android.net.NetworkInfo; 40 import android.net.NetworkInfo.DetailedState; 41 import android.net.NetworkStateTracker; 42 import android.net.RouteInfo; 43 import android.os.Handler; 44 import android.os.INetworkManagementService; 45 import android.test.AndroidTestCase; 46 import android.test.suitebuilder.annotation.LargeTest; 47 import android.util.Log; 48 import android.util.LogPrinter; 49 50 import org.mockito.ArgumentCaptor; 51 52 import java.net.InetAddress; 53 import java.util.concurrent.Future; 54 55 /** 56 * Tests for {@link ConnectivityService}. 57 */ 58 @LargeTest 59 public class ConnectivityServiceTest extends AndroidTestCase { 60 private static final String TAG = "ConnectivityServiceTest"; 61 62 private static final String MOBILE_IFACE = "rmnet3"; 63 private static final String WIFI_IFACE = "wlan6"; 64 65 private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"), 66 MOBILE_IFACE); 67 private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"), 68 MOBILE_IFACE); 69 70 private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(parse("192.168.0.66"), 71 parse("192.168.0.1"), 72 WIFI_IFACE); 73 private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::66"), 74 parse("fd00::"), 75 WIFI_IFACE); 76 77 private INetworkManagementService mNetManager; 78 private INetworkStatsService mStatsService; 79 private INetworkPolicyManager mPolicyService; 80 private ConnectivityService.NetworkFactory mNetFactory; 81 82 private BroadcastInterceptingContext mServiceContext; 83 private ConnectivityService mService; 84 85 private MockNetwork mMobile; 86 private MockNetwork mWifi; 87 88 private Handler mTrackerHandler; 89 90 private static class MockNetwork { 91 public NetworkStateTracker tracker; 92 public NetworkInfo info; 93 public LinkProperties link; 94 95 public MockNetwork(int type) { 96 tracker = mock(NetworkStateTracker.class); 97 info = new NetworkInfo(type, -1, getNetworkTypeName(type), null); 98 link = new LinkProperties(); 99 } 100 101 public void doReturnDefaults() { 102 // TODO: eventually CS should make defensive copies 103 doReturn(new NetworkInfo(info)).when(tracker).getNetworkInfo(); 104 doReturn(new LinkProperties(link)).when(tracker).getLinkProperties(); 105 106 // fallback to default TCP buffers 107 doReturn("").when(tracker).getTcpBufferSizesPropName(); 108 } 109 } 110 111 @Override 112 public void setUp() throws Exception { 113 super.setUp(); 114 115 mServiceContext = new BroadcastInterceptingContext(getContext()); 116 117 mNetManager = mock(INetworkManagementService.class); 118 mStatsService = mock(INetworkStatsService.class); 119 mPolicyService = mock(INetworkPolicyManager.class); 120 mNetFactory = mock(ConnectivityService.NetworkFactory.class); 121 122 mMobile = new MockNetwork(TYPE_MOBILE); 123 mWifi = new MockNetwork(TYPE_WIFI); 124 125 // omit most network trackers 126 doThrow(new IllegalArgumentException("Not supported in test environment")) 127 .when(mNetFactory).createTracker(anyInt(), isA(NetworkConfig.class)); 128 129 doReturn(mMobile.tracker) 130 .when(mNetFactory).createTracker(eq(TYPE_MOBILE), isA(NetworkConfig.class)); 131 doReturn(mWifi.tracker) 132 .when(mNetFactory).createTracker(eq(TYPE_WIFI), isA(NetworkConfig.class)); 133 134 final ArgumentCaptor<Handler> trackerHandler = ArgumentCaptor.forClass(Handler.class); 135 doNothing().when(mMobile.tracker) 136 .startMonitoring(isA(Context.class), trackerHandler.capture()); 137 138 mService = new ConnectivityService( 139 mServiceContext, mNetManager, mStatsService, mPolicyService, mNetFactory); 140 mService.systemReady(); 141 142 mTrackerHandler = trackerHandler.getValue(); 143 mTrackerHandler.getLooper().setMessageLogging(new LogPrinter(Log.INFO, TAG)); 144 } 145 146 @Override 147 public void tearDown() throws Exception { 148 super.tearDown(); 149 } 150 151 public void testMobileConnectedAddedRoutes() throws Exception { 152 Future<?> nextConnBroadcast; 153 154 // bring up mobile network 155 mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null); 156 mMobile.link.setInterfaceName(MOBILE_IFACE); 157 mMobile.link.addRoute(MOBILE_ROUTE_V4); 158 mMobile.link.addRoute(MOBILE_ROUTE_V6); 159 mMobile.doReturnDefaults(); 160 161 nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE); 162 mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); 163 nextConnBroadcast.get(); 164 165 // verify that both routes were added and DNS was flushed 166 verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4)); 167 verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6)); 168 verify(mNetManager).flushInterfaceDnsCache(MOBILE_IFACE); 169 170 } 171 172 public void testMobileWifiHandoff() throws Exception { 173 Future<?> nextConnBroadcast; 174 175 // bring up mobile network 176 mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null); 177 mMobile.link.setInterfaceName(MOBILE_IFACE); 178 mMobile.link.addRoute(MOBILE_ROUTE_V4); 179 mMobile.link.addRoute(MOBILE_ROUTE_V6); 180 mMobile.doReturnDefaults(); 181 182 nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE); 183 mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); 184 nextConnBroadcast.get(); 185 186 reset(mNetManager); 187 188 // now bring up wifi network 189 mWifi.info.setDetailedState(DetailedState.CONNECTED, null, null); 190 mWifi.link.setInterfaceName(WIFI_IFACE); 191 mWifi.link.addRoute(WIFI_ROUTE_V4); 192 mWifi.link.addRoute(WIFI_ROUTE_V6); 193 mWifi.doReturnDefaults(); 194 195 // expect that mobile will be torn down 196 doReturn(true).when(mMobile.tracker).teardown(); 197 198 nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE); 199 mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget(); 200 nextConnBroadcast.get(); 201 202 // verify that wifi routes added, and teardown requested 203 verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V4)); 204 verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V6)); 205 verify(mNetManager).flushInterfaceDnsCache(WIFI_IFACE); 206 verify(mMobile.tracker).teardown(); 207 208 reset(mNetManager, mMobile.tracker); 209 210 // tear down mobile network, as requested 211 mMobile.info.setDetailedState(DetailedState.DISCONNECTED, null, null); 212 mMobile.link.clear(); 213 mMobile.doReturnDefaults(); 214 215 nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE); 216 mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); 217 nextConnBroadcast.get(); 218 219 verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4)); 220 verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6)); 221 222 } 223 224 private static InetAddress parse(String addr) { 225 return InetAddress.parseNumericAddress(addr); 226 } 227 } 228