1 /* 2 * Copyright (C) 2020 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.vcn; 18 19 import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; 20 import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; 21 import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent; 22 import static com.android.server.vcn.VcnTestUtils.setupIpSecManager; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertNull; 26 import static org.mockito.Matchers.any; 27 import static org.mockito.Matchers.eq; 28 import static org.mockito.Mockito.CALLS_REAL_METHODS; 29 import static org.mockito.Mockito.atLeastOnce; 30 import static org.mockito.Mockito.doReturn; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.verifyNoMoreInteractions; 36 37 import android.annotation.NonNull; 38 import android.content.Context; 39 import android.net.ConnectivityManager; 40 import android.net.InetAddresses; 41 import android.net.IpSecConfig; 42 import android.net.IpSecManager; 43 import android.net.IpSecTransform; 44 import android.net.IpSecTunnelInterfaceResponse; 45 import android.net.LinkAddress; 46 import android.net.LinkProperties; 47 import android.net.Network; 48 import android.net.NetworkCapabilities; 49 import android.net.ipsec.ike.ChildSessionCallback; 50 import android.net.ipsec.ike.IkeSessionCallback; 51 import android.net.vcn.VcnGatewayConnectionConfig; 52 import android.net.vcn.VcnGatewayConnectionConfigTest; 53 import android.os.ParcelUuid; 54 import android.os.PowerManager; 55 import android.os.test.TestLooper; 56 import android.telephony.SubscriptionInfo; 57 58 import com.android.internal.util.State; 59 import com.android.internal.util.WakeupMessage; 60 import com.android.server.IpSecService; 61 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; 62 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; 63 import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback; 64 import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock; 65 66 import org.junit.Before; 67 import org.mockito.ArgumentCaptor; 68 69 import java.net.InetAddress; 70 import java.util.Collections; 71 import java.util.UUID; 72 import java.util.concurrent.TimeUnit; 73 74 public class VcnGatewayConnectionTestBase { 75 protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID()); 76 protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class); 77 78 static { 79 doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid(); 80 } 81 82 protected static final InetAddress TEST_DNS_ADDR = 83 InetAddresses.parseNumericAddress("2001:DB8:0:1::"); 84 protected static final InetAddress TEST_DNS_ADDR_2 = 85 InetAddresses.parseNumericAddress("2001:DB8:0:2::"); 86 protected static final LinkAddress TEST_INTERNAL_ADDR = 87 new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:1::"), 64); 88 protected static final LinkAddress TEST_INTERNAL_ADDR_2 = 89 new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:2::"), 64); 90 protected static final LinkAddress TEST_INTERNAL_ADDR_3 = 91 new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:3::"), 64); 92 93 protected static final int TEST_IPSEC_SPI_VALUE = 0x1234; 94 protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1; 95 protected static final int TEST_IPSEC_TRANSFORM_RESOURCE_ID = 2; 96 protected static final int TEST_IPSEC_TUNNEL_RESOURCE_ID = 3; 97 protected static final int TEST_SUB_ID = 5; 98 protected static final long ELAPSED_REAL_TIME = 123456789L; 99 protected static final String TEST_IPSEC_TUNNEL_IFACE = "IPSEC_IFACE"; 100 101 protected static final String TEST_TCP_BUFFER_SIZES_1 = "1,2,3,4"; 102 protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_1 = 103 new UnderlyingNetworkRecord( 104 mock(Network.class, CALLS_REAL_METHODS), 105 new NetworkCapabilities(), 106 new LinkProperties(), 107 false /* blocked */); 108 109 static { 110 TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.setMtu(1500); 111 TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES_1); 112 } 113 114 protected static final String TEST_TCP_BUFFER_SIZES_2 = "2,3,4,5"; 115 protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_2 = 116 new UnderlyingNetworkRecord( 117 mock(Network.class, CALLS_REAL_METHODS), 118 new NetworkCapabilities(), 119 new LinkProperties(), 120 false /* blocked */); 121 122 static { 123 TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.setMtu(1460); 124 TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES_2); 125 } 126 127 protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT = 128 new TelephonySubscriptionSnapshot( 129 TEST_SUB_ID, 130 Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), 131 Collections.EMPTY_MAP); 132 133 @NonNull protected final Context mContext; 134 @NonNull protected final TestLooper mTestLooper; 135 @NonNull protected final VcnNetworkProvider mVcnNetworkProvider; 136 @NonNull protected final VcnContext mVcnContext; 137 @NonNull protected final VcnGatewayConnectionConfig mConfig; 138 @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback; 139 @NonNull protected final VcnGatewayConnection.Dependencies mDeps; 140 @NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker; 141 @NonNull protected final VcnWakeLock mWakeLock; 142 @NonNull protected final WakeupMessage mTeardownTimeoutAlarm; 143 @NonNull protected final WakeupMessage mDisconnectRequestAlarm; 144 @NonNull protected final WakeupMessage mRetryTimeoutAlarm; 145 @NonNull protected final WakeupMessage mSafeModeTimeoutAlarm; 146 147 @NonNull protected final IpSecService mIpSecSvc; 148 @NonNull protected final ConnectivityManager mConnMgr; 149 150 protected VcnIkeSession mMockIkeSession; 151 protected VcnGatewayConnection mGatewayConnection; 152 VcnGatewayConnectionTestBase()153 public VcnGatewayConnectionTestBase() { 154 mContext = mock(Context.class); 155 mTestLooper = new TestLooper(); 156 mVcnNetworkProvider = mock(VcnNetworkProvider.class); 157 mVcnContext = mock(VcnContext.class); 158 mConfig = VcnGatewayConnectionConfigTest.buildTestConfig(); 159 mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class); 160 mDeps = mock(VcnGatewayConnection.Dependencies.class); 161 mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class); 162 mWakeLock = mock(VcnWakeLock.class); 163 mTeardownTimeoutAlarm = mock(WakeupMessage.class); 164 mDisconnectRequestAlarm = mock(WakeupMessage.class); 165 mRetryTimeoutAlarm = mock(WakeupMessage.class); 166 mSafeModeTimeoutAlarm = mock(WakeupMessage.class); 167 168 mIpSecSvc = mock(IpSecService.class); 169 setupIpSecManager(mContext, mIpSecSvc); 170 171 mConnMgr = mock(ConnectivityManager.class); 172 VcnTestUtils.setupSystemService( 173 mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); 174 175 doReturn(mContext).when(mVcnContext).getContext(); 176 doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); 177 doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); 178 179 doReturn(mUnderlyingNetworkTracker) 180 .when(mDeps) 181 .newUnderlyingNetworkTracker(any(), any(), any(), any()); 182 doReturn(mWakeLock) 183 .when(mDeps) 184 .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); 185 186 setUpWakeupMessage(mTeardownTimeoutAlarm, VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM); 187 setUpWakeupMessage(mDisconnectRequestAlarm, VcnGatewayConnection.DISCONNECT_REQUEST_ALARM); 188 setUpWakeupMessage(mRetryTimeoutAlarm, VcnGatewayConnection.RETRY_TIMEOUT_ALARM); 189 setUpWakeupMessage(mSafeModeTimeoutAlarm, VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM); 190 191 doReturn(ELAPSED_REAL_TIME).when(mDeps).getElapsedRealTime(); 192 } 193 setUpWakeupMessage(@onNull WakeupMessage msg, @NonNull String cmdName)194 private void setUpWakeupMessage(@NonNull WakeupMessage msg, @NonNull String cmdName) { 195 doReturn(msg).when(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(cmdName), any()); 196 } 197 198 @Before setUp()199 public void setUp() throws Exception { 200 IpSecTunnelInterfaceResponse resp = 201 new IpSecTunnelInterfaceResponse( 202 IpSecManager.Status.OK, 203 TEST_IPSEC_TUNNEL_RESOURCE_ID, 204 TEST_IPSEC_TUNNEL_IFACE); 205 doReturn(resp).when(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any()); 206 207 mMockIkeSession = mock(VcnIkeSession.class); 208 doReturn(mMockIkeSession).when(mDeps).newIkeSession(any(), any(), any(), any(), any()); 209 210 mGatewayConnection = 211 new VcnGatewayConnection( 212 mVcnContext, 213 TEST_SUB_GRP, 214 TEST_SUBSCRIPTION_SNAPSHOT, 215 mConfig, 216 mGatewayStatusCallback, 217 true /* isMobileDataEnabled */, 218 mDeps); 219 } 220 makeDummyIpSecTransform()221 protected IpSecTransform makeDummyIpSecTransform() throws Exception { 222 return new IpSecTransform(mContext, new IpSecConfig()); 223 } 224 getIkeSessionCallback()225 protected IkeSessionCallback getIkeSessionCallback() { 226 ArgumentCaptor<IkeSessionCallback> captor = 227 ArgumentCaptor.forClass(IkeSessionCallback.class); 228 verify(mDeps).newIkeSession(any(), any(), any(), captor.capture(), any()); 229 return captor.getValue(); 230 } 231 getChildSessionCallback()232 protected VcnChildSessionCallback getChildSessionCallback() { 233 ArgumentCaptor<ChildSessionCallback> captor = 234 ArgumentCaptor.forClass(ChildSessionCallback.class); 235 verify(mDeps, atLeastOnce()).newIkeSession(any(), any(), any(), any(), captor.capture()); 236 return (VcnChildSessionCallback) captor.getValue(); 237 } 238 verifyWakeLockSetUp()239 protected void verifyWakeLockSetUp() { 240 verify(mDeps).newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); 241 verifyNoMoreInteractions(mWakeLock); 242 } 243 verifyWakeLockAcquired()244 protected void verifyWakeLockAcquired() { 245 verify(mWakeLock).acquire(); 246 verifyNoMoreInteractions(mWakeLock); 247 } 248 verifyWakeLockReleased()249 protected void verifyWakeLockReleased() { 250 verify(mWakeLock).release(); 251 verifyNoMoreInteractions(mWakeLock); 252 } 253 verifyWakeupMessageSetUpAndGetCallback( @onNull String tag, @NonNull WakeupMessage msg, long delayInMillis, boolean expectCanceled)254 private Runnable verifyWakeupMessageSetUpAndGetCallback( 255 @NonNull String tag, 256 @NonNull WakeupMessage msg, 257 long delayInMillis, 258 boolean expectCanceled) { 259 ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); 260 verify(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(tag), runnableCaptor.capture()); 261 262 verify(mDeps, atLeastOnce()).getElapsedRealTime(); 263 verify(msg).schedule(ELAPSED_REAL_TIME + delayInMillis); 264 verify(msg, expectCanceled ? times(1) : never()).cancel(); 265 266 return runnableCaptor.getValue(); 267 } 268 verifyTeardownTimeoutAlarmAndGetCallback(boolean expectCanceled)269 protected Runnable verifyTeardownTimeoutAlarmAndGetCallback(boolean expectCanceled) { 270 return verifyWakeupMessageSetUpAndGetCallback( 271 VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM, 272 mTeardownTimeoutAlarm, 273 TimeUnit.SECONDS.toMillis(VcnGatewayConnection.TEARDOWN_TIMEOUT_SECONDS), 274 expectCanceled); 275 } 276 verifyDisconnectRequestAlarmAndGetCallback(boolean expectCanceled)277 protected Runnable verifyDisconnectRequestAlarmAndGetCallback(boolean expectCanceled) { 278 return verifyWakeupMessageSetUpAndGetCallback( 279 VcnGatewayConnection.DISCONNECT_REQUEST_ALARM, 280 mDisconnectRequestAlarm, 281 TimeUnit.SECONDS.toMillis( 282 VcnGatewayConnection.NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS), 283 expectCanceled); 284 } 285 verifyRetryTimeoutAlarmAndGetCallback( long delayInMillis, boolean expectCanceled)286 protected Runnable verifyRetryTimeoutAlarmAndGetCallback( 287 long delayInMillis, boolean expectCanceled) { 288 return verifyWakeupMessageSetUpAndGetCallback( 289 VcnGatewayConnection.RETRY_TIMEOUT_ALARM, 290 mRetryTimeoutAlarm, 291 delayInMillis, 292 expectCanceled); 293 } 294 verifySafeModeTimeoutAlarmAndGetCallback(boolean expectCanceled)295 protected Runnable verifySafeModeTimeoutAlarmAndGetCallback(boolean expectCanceled) { 296 return verifyWakeupMessageSetUpAndGetCallback( 297 VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM, 298 mSafeModeTimeoutAlarm, 299 TimeUnit.SECONDS.toMillis(VcnGatewayConnection.SAFEMODE_TIMEOUT_SECONDS), 300 expectCanceled); 301 } 302 verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode)303 protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) { 304 verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged(); 305 assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode()); 306 } 307 verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent( @onNull State expectedState)308 protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent( 309 @NonNull State expectedState) { 310 // Set a VcnNetworkAgent, and expect it to be unregistered and cleared 311 final VcnNetworkAgent mockNetworkAgent = mock(VcnNetworkAgent.class); 312 mGatewayConnection.setNetworkAgent(mockNetworkAgent); 313 314 // SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial 315 // state) 316 final Runnable delayedEvent = 317 verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); 318 delayedEvent.run(); 319 mTestLooper.dispatchAll(); 320 321 assertEquals(expectedState, mGatewayConnection.getCurrentState()); 322 verifySafeModeStateAndCallbackFired(1, true); 323 324 verify(mockNetworkAgent).unregister(); 325 assertNull(mGatewayConnection.getNetworkAgent()); 326 } 327 } 328