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