1 /* 2 * Copyright (C) 2022 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.connectivity; 18 19 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 20 import static android.net.ConnectivityManager.TYPE_MOBILE; 21 import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE; 22 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 23 import static com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.METRICS_COLLECTION_DURATION_MS; 24 import static com.android.testutils.HandlerUtils.visibleOnHandlerThread; 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotNull; 28 import static org.junit.Assert.assertNull; 29 import static org.junit.Assert.assertThrows; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 import static org.mockito.ArgumentMatchers.any; 33 import static org.mockito.ArgumentMatchers.anyInt; 34 import static org.mockito.ArgumentMatchers.eq; 35 import static org.mockito.ArgumentMatchers.longThat; 36 import static org.mockito.Mockito.clearInvocations; 37 import static org.mockito.Mockito.doCallRealMethod; 38 import static org.mockito.Mockito.doNothing; 39 import static org.mockito.Mockito.doReturn; 40 import static org.mockito.Mockito.ignoreStubs; 41 import static org.mockito.Mockito.mock; 42 import static org.mockito.Mockito.never; 43 import static org.mockito.Mockito.spy; 44 import static org.mockito.Mockito.verify; 45 import static org.mockito.Mockito.verifyNoMoreInteractions; 46 47 import android.app.AlarmManager; 48 import android.content.Context; 49 import android.content.res.Resources; 50 import android.net.INetd; 51 import android.net.ISocketKeepaliveCallback; 52 import android.net.InetAddresses; 53 import android.net.KeepalivePacketData; 54 import android.net.LinkAddress; 55 import android.net.LinkProperties; 56 import android.net.MarkMaskParcel; 57 import android.net.NattKeepalivePacketData; 58 import android.net.Network; 59 import android.net.NetworkCapabilities; 60 import android.net.NetworkInfo; 61 import android.net.SocketKeepalive; 62 import android.net.TcpKeepalivePacketData; 63 import android.os.Binder; 64 import android.os.Build; 65 import android.os.Handler; 66 import android.os.HandlerThread; 67 import android.os.IBinder; 68 import android.os.Looper; 69 import android.os.Message; 70 import android.os.SystemClock; 71 import android.telephony.SubscriptionManager; 72 import android.util.Log; 73 import androidx.annotation.NonNull; 74 import androidx.annotation.Nullable; 75 import androidx.test.filters.SmallTest; 76 import com.android.internal.util.IndentingPrintWriter; 77 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive; 78 import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo; 79 import com.android.testutils.DevSdkIgnoreRule; 80 import com.android.testutils.DevSdkIgnoreRunner; 81 import com.android.testutils.HandlerUtils; 82 import java.io.FileDescriptor; 83 import java.io.StringWriter; 84 import java.net.Inet4Address; 85 import java.net.InetAddress; 86 import java.net.Socket; 87 import java.nio.ByteBuffer; 88 import java.nio.ByteOrder; 89 import java.util.ArrayList; 90 import java.util.List; 91 import libcore.util.HexEncoding; 92 import org.junit.After; 93 import org.junit.Before; 94 import org.junit.Test; 95 import org.junit.runner.RunWith; 96 import org.mockito.ArgumentCaptor; 97 import org.mockito.Mock; 98 import org.mockito.MockitoAnnotations; 99 100 @RunWith(DevSdkIgnoreRunner.class) 101 @SmallTest 102 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) 103 public class AutomaticOnOffKeepaliveTrackerTest { 104 private static final String TAG = AutomaticOnOffKeepaliveTrackerTest.class.getSimpleName(); 105 private static final int TEST_SLOT = 1; 106 private static final int TEST_NETID = 0xA85; 107 private static final int TEST_NETID_FWMARK = 0x0A85; 108 private static final int OTHER_NETID = 0x1A85; 109 private static final int NETID_MASK = 0xffff; 110 private static final int TIMEOUT_MS = 30_000; 111 private static final int MOCK_RESOURCE_ID = 5; 112 private static final int TEST_KEEPALIVE_INTERVAL_SEC = 10; 113 private static final int TEST_KEEPALIVE_INVALID_INTERVAL_SEC = 9; 114 private static final byte[] V4_SRC_ADDR = new byte[] { (byte) 192, 0, 0, (byte) 129 }; 115 private static final String TEST_V4_IFACE = "v4-testIface"; 116 private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker; 117 private HandlerThread mHandlerThread; 118 119 @Mock INetd mNetd; 120 @Mock AutomaticOnOffKeepaliveTracker.Dependencies mDependencies; 121 @Mock Context mCtx; 122 @Mock AlarmManager mAlarmManager; 123 @Mock NetworkAgentInfo mNai; 124 @Mock SubscriptionManager mSubscriptionManager; 125 @Mock KeepaliveTracker.Dependencies mKeepaliveTrackerDeps; 126 KeepaliveStatsTracker mKeepaliveStatsTracker; 127 TestKeepaliveTracker mKeepaliveTracker; 128 AOOTestHandler mTestHandler; 129 TestTcpKeepaliveController mTcpController; 130 131 // Hexadecimal representation of a SOCK_DIAG response with tcp info. 132 private static final String SOCK_DIAG_TCP_INET_HEX = 133 // struct nlmsghdr. 134 "14010000" // length = 276 135 + "1400" // type = SOCK_DIAG_BY_FAMILY 136 + "0301" // flags = NLM_F_REQUEST | NLM_F_DUMP 137 + "00000000" // seqno 138 + "00000000" // pid (0 == kernel) 139 // struct inet_diag_req_v2 140 + "02" // family = AF_INET 141 + "06" // state 142 + "00" // timer 143 + "00" // retrans 144 // inet_diag_sockid 145 + "DEA5" // idiag_sport = 42462 146 + "71B9" // idiag_dport = 47473 147 + "0a006402000000000000000000000000" // idiag_src = 10.0.100.2 148 + "08080808000000000000000000000000" // idiag_dst = 8.8.8.8 149 + "00000000" // idiag_if 150 + "34ED000076270000" // idiag_cookie = 43387759684916 151 + "00000000" // idiag_expires 152 + "00000000" // idiag_rqueue 153 + "00000000" // idiag_wqueue 154 + "39300000" // idiag_uid = 12345 155 + "00000000" // idiag_inode 156 // rtattr 157 + "0500" // len = 5 158 + "0800" // type = 8 159 + "00000000" // data 160 + "0800" // len = 8 161 + "0F00" // type = 15(INET_DIAG_MARK) 162 + "850A0C00" // data, socket mark=789125 163 + "AC00" // len = 172 164 + "0200" // type = 2(INET_DIAG_INFO) 165 // tcp_info 166 + "01" // state = TCP_ESTABLISHED 167 + "00" // ca_state = TCP_CA_OPEN 168 + "05" // retransmits = 5 169 + "00" // probes = 0 170 + "00" // backoff = 0 171 + "07" // option = TCPI_OPT_WSCALE|TCPI_OPT_SACK|TCPI_OPT_TIMESTAMPS 172 + "88" // wscale = 8 173 + "00" // delivery_rate_app_limited = 0 174 + "4A911B00" // rto = 1806666 175 + "00000000" // ato = 0 176 + "2E050000" // sndMss = 1326 177 + "18020000" // rcvMss = 536 178 + "00000000" // unsacked = 0 179 + "00000000" // acked = 0 180 + "00000000" // lost = 0 181 + "00000000" // retrans = 0 182 + "00000000" // fackets = 0 183 + "BB000000" // lastDataSent = 187 184 + "00000000" // lastAckSent = 0 185 + "BB000000" // lastDataRecv = 187 186 + "BB000000" // lastDataAckRecv = 187 187 + "DC050000" // pmtu = 1500 188 + "30560100" // rcvSsthresh = 87600 189 + "3E2C0900" // rttt = 601150 190 + "1F960400" // rttvar = 300575 191 + "78050000" // sndSsthresh = 1400 192 + "0A000000" // sndCwnd = 10 193 + "A8050000" // advmss = 1448 194 + "03000000" // reordering = 3 195 + "00000000" // rcvrtt = 0 196 + "30560100" // rcvspace = 87600 197 + "00000000" // totalRetrans = 0 198 + "53AC000000000000" // pacingRate = 44115 199 + "FFFFFFFFFFFFFFFF" // maxPacingRate = 18446744073709551615 200 + "0100000000000000" // bytesAcked = 1 201 + "0000000000000000" // bytesReceived = 0 202 + "0A000000" // SegsOut = 10 203 + "00000000" // SegsIn = 0 204 + "00000000" // NotSentBytes = 0 205 + "3E2C0900" // minRtt = 601150 206 + "00000000" // DataSegsIn = 0 207 + "00000000" // DataSegsOut = 0 208 + "0000000000000000"; // deliverRate = 0 209 private static final String SOCK_DIAG_NO_TCP_INET_HEX = 210 // struct nlmsghdr 211 "14000000" // length = 20 212 + "0300" // type = NLMSG_DONE 213 + "0301" // flags = NLM_F_REQUEST | NLM_F_DUMP 214 + "00000000" // seqno 215 + "00000000" // pid (0 == kernel) 216 // struct inet_diag_req_v2 217 + "02" // family = AF_INET 218 + "06" // state 219 + "00" // timer 220 + "00"; // retrans 221 private static final byte[] SOCK_DIAG_NO_TCP_INET_BYTES = 222 HexEncoding.decode(SOCK_DIAG_NO_TCP_INET_HEX.toCharArray(), false); 223 private static final String TEST_RESPONSE_HEX = 224 SOCK_DIAG_TCP_INET_HEX + SOCK_DIAG_NO_TCP_INET_HEX; 225 private static final byte[] TEST_RESPONSE_BYTES = 226 HexEncoding.decode(TEST_RESPONSE_HEX.toCharArray(), false); 227 228 private static class TestKeepaliveInfo { 229 private static List<Socket> sOpenSockets = new ArrayList<>(); 230 closeAllSockets()231 public static void closeAllSockets() throws Exception { 232 for (final Socket socket : sOpenSockets) { 233 socket.close(); 234 } 235 sOpenSockets.clear(); 236 } 237 238 public final Socket socket; 239 public final Binder binder; 240 public final FileDescriptor fd; 241 public final ISocketKeepaliveCallback socketKeepaliveCallback; 242 public final Network underpinnedNetwork; 243 public final KeepalivePacketData kpd; 244 TestKeepaliveInfo(KeepalivePacketData kpd)245 TestKeepaliveInfo(KeepalivePacketData kpd) throws Exception { 246 this.kpd = kpd; 247 socket = new Socket(); 248 socket.bind(null); 249 sOpenSockets.add(socket); 250 fd = socket.getFileDescriptor$(); 251 252 binder = new Binder(); 253 socketKeepaliveCallback = mock(ISocketKeepaliveCallback.class); 254 doReturn(binder).when(socketKeepaliveCallback).asBinder(); 255 underpinnedNetwork = mock(Network.class); 256 } 257 } 258 259 private class TestKeepaliveTracker extends KeepaliveTracker { 260 private KeepaliveInfo mKi; 261 TestKeepaliveTracker(@onNull final Context context, @NonNull final Handler handler, @NonNull final TcpKeepaliveController tcpController)262 TestKeepaliveTracker(@NonNull final Context context, @NonNull final Handler handler, 263 @NonNull final TcpKeepaliveController tcpController) { 264 super(context, handler, tcpController, mKeepaliveTrackerDeps); 265 } 266 setReturnedKeepaliveInfo(@onNull final KeepaliveInfo ki)267 public void setReturnedKeepaliveInfo(@NonNull final KeepaliveInfo ki) { 268 mKi = ki; 269 } 270 271 @NonNull 272 @Override makeNattKeepaliveInfo(@ullable final NetworkAgentInfo nai, @Nullable final FileDescriptor fd, final int intervalSeconds, @NonNull final ISocketKeepaliveCallback cb, @NonNull final String srcAddrString, final int srcPort, @NonNull final String dstAddrString, final int dstPort)273 public KeepaliveInfo makeNattKeepaliveInfo(@Nullable final NetworkAgentInfo nai, 274 @Nullable final FileDescriptor fd, final int intervalSeconds, 275 @NonNull final ISocketKeepaliveCallback cb, @NonNull final String srcAddrString, 276 final int srcPort, 277 @NonNull final String dstAddrString, final int dstPort) { 278 if (null == mKi) { 279 throw new IllegalStateException("Must call setReturnedKeepaliveInfo"); 280 } 281 return mKi; 282 } 283 284 @NonNull 285 @Override makeTcpKeepaliveInfo(@ullable final NetworkAgentInfo nai, @Nullable final FileDescriptor fd, final int intervalSeconds, @NonNull final ISocketKeepaliveCallback cb)286 public KeepaliveInfo makeTcpKeepaliveInfo(@Nullable final NetworkAgentInfo nai, 287 @Nullable final FileDescriptor fd, final int intervalSeconds, 288 @NonNull final ISocketKeepaliveCallback cb) { 289 if (null == mKi) { 290 throw new IllegalStateException("Please call `setReturnedKeepaliveInfo`" 291 + " before makeTcpKeepaliveInfo is called"); 292 } 293 return mKi; 294 } 295 } 296 297 private static class TestTcpKeepaliveController extends TcpKeepaliveController { TestTcpKeepaliveController(final Handler connectivityServiceHandler)298 TestTcpKeepaliveController(final Handler connectivityServiceHandler) { 299 super(connectivityServiceHandler); 300 } 301 } 302 mockService(String serviceName, Class<T> serviceClass, T service)303 private <T> void mockService(String serviceName, Class<T> serviceClass, T service) { 304 doReturn(serviceName).when(mCtx).getSystemServiceName(serviceClass); 305 doReturn(service).when(mCtx).getSystemService(serviceName); 306 if (mCtx.getSystemService(serviceClass) == null) { 307 // Test is using mockito-extended 308 doCallRealMethod().when(mCtx).getSystemService(serviceClass); 309 } 310 } 311 312 @Before setup()313 public void setup() throws Exception { 314 MockitoAnnotations.initMocks(this); 315 316 mockService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class, 317 mSubscriptionManager); 318 319 mNai.networkCapabilities = 320 new NetworkCapabilities.Builder().addTransportType(TRANSPORT_CELLULAR).build(); 321 mNai.networkInfo = new NetworkInfo(TYPE_MOBILE, 0 /* subtype */, "LTE", "LTE"); 322 mNai.networkInfo.setDetailedState( 323 NetworkInfo.DetailedState.CONNECTED, "test reason", "test extra info"); 324 doReturn(new Network(TEST_NETID)).when(mNai).network(); 325 mNai.linkProperties = new LinkProperties(); 326 doReturn(null).when(mNai).translateV4toClatV6(any()); 327 doReturn(null).when(mNai).getClatv6SrcAddress(); 328 329 doReturn(PERMISSION_GRANTED).when(mCtx).checkPermission(any() /* permission */, 330 anyInt() /* pid */, anyInt() /* uid */); 331 ConnectivityResources.setResourcesContextForTest(mCtx); 332 final Resources mockResources = mock(Resources.class); 333 doReturn(mockResources).when(mCtx).getResources(); 334 doReturn(mNetd).when(mDependencies).getNetd(); 335 doReturn(mAlarmManager).when(mDependencies).getAlarmManager(any()); 336 doReturn(makeMarkMaskParcel(NETID_MASK, TEST_NETID_FWMARK)).when(mNetd) 337 .getFwmarkForNetwork(TEST_NETID); 338 339 doNothing().when(mDependencies).sendRequest(any(), any()); 340 doReturn(true).when(mKeepaliveTrackerDeps).isAddressTranslationEnabled(mCtx); 341 doReturn(new ConnectivityResources(mCtx)).when(mKeepaliveTrackerDeps) 342 .createConnectivityResources(mCtx); 343 doReturn(new int[] {3, 0, 0, 3}).when(mKeepaliveTrackerDeps).getSupportedKeepalives(mCtx); 344 345 mHandlerThread = new HandlerThread("KeepaliveTrackerTest"); 346 mHandlerThread.start(); 347 mTestHandler = new AOOTestHandler(mHandlerThread.getLooper()); 348 mTcpController = new TestTcpKeepaliveController(mTestHandler); 349 mKeepaliveTracker = new TestKeepaliveTracker(mCtx, mTestHandler, mTcpController); 350 mKeepaliveStatsTracker = spy(new KeepaliveStatsTracker(mCtx, mTestHandler)); 351 doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(mCtx, mTestHandler); 352 doReturn(mKeepaliveStatsTracker) 353 .when(mDependencies) 354 .newKeepaliveStatsTracker(mCtx, mTestHandler); 355 356 doReturn(true).when(mDependencies).isTetheringFeatureNotChickenedOut(any()); 357 doReturn(0L).when(mDependencies).getElapsedRealtime(); 358 mAOOKeepaliveTracker = 359 new AutomaticOnOffKeepaliveTracker(mCtx, mTestHandler, mDependencies); 360 } 361 362 @After teardown()363 public void teardown() throws Exception { 364 TestKeepaliveInfo.closeAllSockets(); 365 if (mHandlerThread != null) { 366 mHandlerThread.quitSafely(); 367 mHandlerThread.join(); 368 } 369 } 370 371 private final class AOOTestHandler extends Handler { 372 public AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive mLastAutoKi = null; 373 AOOTestHandler(@onNull final Looper looper)374 AOOTestHandler(@NonNull final Looper looper) { 375 super(looper); 376 } 377 378 @Override handleMessage(@onNull final Message msg)379 public void handleMessage(@NonNull final Message msg) { 380 switch (msg.what) { 381 case AutomaticOnOffKeepaliveTracker.CMD_REQUEST_START_KEEPALIVE: 382 Log.d(TAG, "Test handler received CMD_REQUEST_START_KEEPALIVE : " + msg); 383 mAOOKeepaliveTracker.handleStartKeepalive(msg); 384 break; 385 case AutomaticOnOffKeepaliveTracker.CMD_MONITOR_AUTOMATIC_KEEPALIVE: 386 Log.d(TAG, "Test handler received CMD_MONITOR_AUTOMATIC_KEEPALIVE : " + msg); 387 mLastAutoKi = mAOOKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj); 388 break; 389 case CMD_STOP_SOCKET_KEEPALIVE: 390 Log.d(TAG, "Test handler received CMD_STOP_SOCKET_KEEPALIVE : " + msg); 391 mLastAutoKi = mAOOKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj); 392 if (mLastAutoKi == null) { 393 fail("Attempt to stop an already stopped keepalive"); 394 } 395 mAOOKeepaliveTracker.handleStopKeepalive(mLastAutoKi, msg.arg2); 396 break; 397 } 398 } 399 } 400 401 @Test testIsAnyTcpSocketConnected_runOnNonHandlerThread()402 public void testIsAnyTcpSocketConnected_runOnNonHandlerThread() throws Exception { 403 setupResponseWithSocketExisting(); 404 assertThrows(IllegalStateException.class, 405 () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID)); 406 } 407 408 @Test testIsAnyTcpSocketConnected_withTargetNetId()409 public void testIsAnyTcpSocketConnected_withTargetNetId() throws Exception { 410 setupResponseWithSocketExisting(); 411 assertTrue(visibleOnHandlerThread(mTestHandler, 412 () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID))); 413 } 414 415 @Test testIsAnyTcpSocketConnected_withIncorrectNetId()416 public void testIsAnyTcpSocketConnected_withIncorrectNetId() throws Exception { 417 setupResponseWithSocketExisting(); 418 assertFalse(visibleOnHandlerThread(mTestHandler, 419 () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(OTHER_NETID))); 420 } 421 422 @Test testIsAnyTcpSocketConnected_noSocketExists()423 public void testIsAnyTcpSocketConnected_noSocketExists() throws Exception { 424 setupResponseWithoutSocketExisting(); 425 assertFalse(visibleOnHandlerThread(mTestHandler, 426 () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID))); 427 } 428 triggerEventKeepalive(int slot, int reason)429 private void triggerEventKeepalive(int slot, int reason) { 430 visibleOnHandlerThread( 431 mTestHandler, 432 () -> mAOOKeepaliveTracker.handleEventSocketKeepalive(mNai, slot, reason)); 433 } 434 doStartNattKeepalive(int intervalSeconds)435 private TestKeepaliveInfo doStartNattKeepalive(int intervalSeconds) throws Exception { 436 final InetAddress srcAddress = InetAddress.getByAddress(V4_SRC_ADDR); 437 final int srcPort = 12345; 438 final InetAddress dstAddress = InetAddress.getByAddress(new byte[] {8, 8, 8, 8}); 439 final int dstPort = 12345; 440 441 mNai.linkProperties.addLinkAddress(new LinkAddress(srcAddress, 24)); 442 443 final NattKeepalivePacketData kpd = new NattKeepalivePacketData(srcAddress, srcPort, 444 dstAddress, dstPort, new byte[] {1}); 445 446 final TestKeepaliveInfo testInfo = new TestKeepaliveInfo(kpd); 447 448 final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo( 449 testInfo.socketKeepaliveCallback, mNai, kpd, intervalSeconds, 450 KeepaliveInfo.TYPE_NATT, testInfo.fd); 451 mKeepaliveTracker.setReturnedKeepaliveInfo(ki); 452 453 mAOOKeepaliveTracker.startNattKeepalive(mNai, testInfo.fd, intervalSeconds, 454 testInfo.socketKeepaliveCallback, srcAddress.toString(), srcPort, 455 dstAddress.toString(), dstPort, true /* automaticOnOffKeepalives */, 456 testInfo.underpinnedNetwork); 457 HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS); 458 459 return testInfo; 460 } 461 doStartNattKeepalive()462 private TestKeepaliveInfo doStartNattKeepalive() throws Exception { 463 return doStartNattKeepalive(TEST_KEEPALIVE_INTERVAL_SEC); 464 } 465 doPauseKeepalive(AutomaticOnOffKeepalive autoKi)466 private void doPauseKeepalive(AutomaticOnOffKeepalive autoKi) throws Exception { 467 setupResponseWithoutSocketExisting(); 468 visibleOnHandlerThread( 469 mTestHandler, 470 () -> mAOOKeepaliveTracker.handleMonitorAutomaticKeepalive(autoKi, TEST_NETID)); 471 } 472 doResumeKeepalive(AutomaticOnOffKeepalive autoKi)473 private void doResumeKeepalive(AutomaticOnOffKeepalive autoKi) throws Exception { 474 setupResponseWithSocketExisting(); 475 visibleOnHandlerThread( 476 mTestHandler, 477 () -> mAOOKeepaliveTracker.handleMonitorAutomaticKeepalive(autoKi, TEST_NETID)); 478 } 479 doStopKeepalive(AutomaticOnOffKeepalive autoKi)480 private void doStopKeepalive(AutomaticOnOffKeepalive autoKi) throws Exception { 481 visibleOnHandlerThread( 482 mTestHandler, 483 () -> mAOOKeepaliveTracker.handleStopKeepalive(autoKi, SocketKeepalive.SUCCESS)); 484 } 485 486 @Test testAlarm()487 public void testAlarm() throws Exception { 488 // Mock elapsed real time to verify the alarm timer. 489 final long time = SystemClock.elapsedRealtime(); 490 doReturn(time).when(mDependencies).getElapsedRealtime(); 491 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 492 493 final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor = 494 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 495 // The alarm timer should be smaller than the keepalive delay. Verify the alarm trigger time 496 // is higher than base time but smaller than the keepalive delay. 497 verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), 498 longThat(t -> t > time + 1000L && t < time + TEST_KEEPALIVE_INTERVAL_SEC * 1000L), 499 any() /* tag */, listenerCaptor.capture(), eq(mTestHandler)); 500 final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue(); 501 502 // For realism, the listener should be posted on the handler 503 visibleOnHandlerThread(mTestHandler, () -> listener.onAlarm()); 504 // Wait for the message posted by the listener to be processed. 505 HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS); 506 507 assertNotNull(mTestHandler.mLastAutoKi); 508 assertEquals(testInfo.socketKeepaliveCallback, mTestHandler.mLastAutoKi.getCallback()); 509 assertEquals(testInfo.underpinnedNetwork, mTestHandler.mLastAutoKi.getUnderpinnedNetwork()); 510 } 511 512 @Test testAlarm_writeMetrics()513 public void testAlarm_writeMetrics() throws Exception { 514 final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor = 515 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 516 517 // First AlarmManager.set call from the constructor. 518 verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), 519 eq(METRICS_COLLECTION_DURATION_MS), any() /* tag */, listenerCaptor.capture(), 520 eq(mTestHandler)); 521 522 final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue(); 523 524 doReturn(METRICS_COLLECTION_DURATION_MS).when(mDependencies).getElapsedRealtime(); 525 // For realism, the listener should be posted on the handler 526 visibleOnHandlerThread(mTestHandler, () -> listener.onAlarm()); 527 528 verify(mKeepaliveStatsTracker).writeAndResetMetrics(); 529 // Alarm is rescheduled. 530 verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), 531 eq(METRICS_COLLECTION_DURATION_MS * 2), 532 any() /* tag */, listenerCaptor.capture(), eq(mTestHandler)); 533 } 534 setupResponseWithSocketExisting()535 private void setupResponseWithSocketExisting() throws Exception { 536 final ByteBuffer tcpBufferV6 = getByteBuffer(TEST_RESPONSE_BYTES); 537 final ByteBuffer tcpBufferV4 = getByteBuffer(TEST_RESPONSE_BYTES); 538 doReturn(tcpBufferV6, tcpBufferV4).when(mDependencies).recvSockDiagResponse(any()); 539 } 540 setupResponseWithoutSocketExisting()541 private void setupResponseWithoutSocketExisting() throws Exception { 542 final ByteBuffer tcpBufferV6 = getByteBuffer(SOCK_DIAG_NO_TCP_INET_BYTES); 543 final ByteBuffer tcpBufferV4 = getByteBuffer(SOCK_DIAG_NO_TCP_INET_BYTES); 544 doReturn(tcpBufferV6, tcpBufferV4).when(mDependencies).recvSockDiagResponse(any()); 545 } 546 makeMarkMaskParcel(final int mask, final int mark)547 private MarkMaskParcel makeMarkMaskParcel(final int mask, final int mark) { 548 final MarkMaskParcel parcel = new MarkMaskParcel(); 549 parcel.mask = mask; 550 parcel.mark = mark; 551 return parcel; 552 } 553 getByteBuffer(final byte[] bytes)554 private ByteBuffer getByteBuffer(final byte[] bytes) { 555 final ByteBuffer buffer = ByteBuffer.wrap(bytes); 556 buffer.order(ByteOrder.nativeOrder()); 557 return buffer; 558 } 559 getAutoKiForBinder(IBinder binder)560 private AutomaticOnOffKeepalive getAutoKiForBinder(IBinder binder) { 561 return visibleOnHandlerThread( 562 mTestHandler, () -> mAOOKeepaliveTracker.getKeepaliveForBinder(binder)); 563 } 564 checkAndProcessKeepaliveStart(final KeepalivePacketData kpd)565 private void checkAndProcessKeepaliveStart(final KeepalivePacketData kpd) throws Exception { 566 checkAndProcessKeepaliveStart(TEST_SLOT, kpd); 567 } 568 checkAndProcessKeepaliveStart( int slot, final KeepalivePacketData kpd)569 private void checkAndProcessKeepaliveStart( 570 int slot, final KeepalivePacketData kpd) throws Exception { 571 verify(mNai).onStartNattSocketKeepalive( 572 slot, TEST_KEEPALIVE_INTERVAL_SEC, (NattKeepalivePacketData) kpd); 573 verify(mNai).onAddNattKeepalivePacketFilter(slot, (NattKeepalivePacketData) kpd); 574 triggerEventKeepalive(slot, SocketKeepalive.SUCCESS); 575 } 576 checkAndProcessKeepaliveStop()577 private void checkAndProcessKeepaliveStop() throws Exception { 578 checkAndProcessKeepaliveStop(TEST_SLOT); 579 } 580 checkAndProcessKeepaliveStop(int slot)581 private void checkAndProcessKeepaliveStop(int slot) throws Exception { 582 verify(mNai).onStopSocketKeepalive(slot); 583 verify(mNai).onRemoveKeepalivePacketFilter(slot); 584 triggerEventKeepalive(slot, SocketKeepalive.SUCCESS); 585 } 586 587 @Test testStartNattKeepalive_valid()588 public void testStartNattKeepalive_valid() throws Exception { 589 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 590 591 checkAndProcessKeepaliveStart(testInfo.kpd); 592 593 final AutomaticOnOffKeepalive autoKi = getAutoKiForBinder(testInfo.binder); 594 assertNotNull(autoKi); 595 assertEquals(testInfo.socketKeepaliveCallback, autoKi.getCallback()); 596 597 verify(testInfo.socketKeepaliveCallback).onStarted(); 598 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 599 } 600 601 @Test testStartNattKeepalive_invalidInterval()602 public void testStartNattKeepalive_invalidInterval() throws Exception { 603 final TestKeepaliveInfo testInfo = 604 doStartNattKeepalive(TEST_KEEPALIVE_INVALID_INTERVAL_SEC); 605 606 assertNull(getAutoKiForBinder(testInfo.binder)); 607 608 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_INTERVAL); 609 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 610 } 611 setupTestNaiForClat(InetAddress v6Src, InetAddress v6Dst)612 private void setupTestNaiForClat(InetAddress v6Src, InetAddress v6Dst) throws Exception { 613 doReturn(v6Dst).when(mNai).translateV4toClatV6(any()); 614 doReturn(v6Src).when(mNai).getClatv6SrcAddress(); 615 doReturn(InetAddress.getByAddress(V4_SRC_ADDR)).when(mNai).getClatv4SrcAddress(); 616 // Setup nai to add clat address 617 final LinkProperties stacked = new LinkProperties(); 618 stacked.setInterfaceName(TEST_V4_IFACE); 619 final InetAddress srcAddress = InetAddress.getByAddress( 620 new byte[] { (byte) 192, 0, 0, (byte) 129 }); 621 mNai.linkProperties.addLinkAddress(new LinkAddress(srcAddress, 24)); 622 mNai.linkProperties.addStackedLink(stacked); 623 } 624 doStartTcpKeepalive(InetAddress srcAddr)625 private TestKeepaliveInfo doStartTcpKeepalive(InetAddress srcAddr) throws Exception { 626 final KeepalivePacketData kpd = new TcpKeepalivePacketData( 627 srcAddr, 628 12345 /* srcPort */, 629 InetAddress.getByAddress(new byte[] { 8, 8, 8, 8}) /* dstAddr */, 630 12345 /* dstPort */, new byte[] {1}, 111 /* tcpSeq */, 631 222 /* tcpAck */, 800 /* tcpWindow */, 2 /* tcpWindowScale */, 632 4 /* ipTos */, 64 /* ipTtl */); 633 final TestKeepaliveInfo testInfo = new TestKeepaliveInfo(kpd); 634 635 final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo( 636 testInfo.socketKeepaliveCallback, mNai, kpd, 637 TEST_KEEPALIVE_INTERVAL_SEC, KeepaliveInfo.TYPE_TCP, testInfo.fd); 638 mKeepaliveTracker.setReturnedKeepaliveInfo(ki); 639 640 // Setup TCP keepalive. 641 mAOOKeepaliveTracker.startTcpKeepalive(mNai, testInfo.fd, TEST_KEEPALIVE_INTERVAL_SEC, 642 testInfo.socketKeepaliveCallback); 643 HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS); 644 return testInfo; 645 } 646 @Test testStartTcpKeepalive_addressTranslationOnClat()647 public void testStartTcpKeepalive_addressTranslationOnClat() throws Exception { 648 setupTestNaiForClat(InetAddresses.parseNumericAddress("2001:db8::1") /* v6Src */, 649 InetAddresses.parseNumericAddress("2001:db8::2") /* v6Dst */); 650 final InetAddress srcAddr = InetAddress.getByAddress(V4_SRC_ADDR); 651 doStartTcpKeepalive(srcAddr); 652 final ArgumentCaptor<TcpKeepalivePacketData> tpdCaptor = 653 ArgumentCaptor.forClass(TcpKeepalivePacketData.class); 654 verify(mNai).onStartTcpSocketKeepalive( 655 eq(TEST_SLOT), eq(TEST_KEEPALIVE_INTERVAL_SEC), tpdCaptor.capture()); 656 final TcpKeepalivePacketData tpd = tpdCaptor.getValue(); 657 // Verify the addresses still be the same address when clat is started. 658 assertEquals(srcAddr, tpd.getSrcAddress()); 659 } 660 661 @Test testStartNattKeepalive_addressTranslationOnClatNotSupported()662 public void testStartNattKeepalive_addressTranslationOnClatNotSupported() throws Exception { 663 // Disable address translation feature and verify the behavior 664 doReturn(false).when(mKeepaliveTrackerDeps).isAddressTranslationEnabled(mCtx); 665 666 setupTestNaiForClat(InetAddresses.parseNumericAddress("2001:db8::1"), 667 InetAddresses.parseNumericAddress("2001:db8::2")); 668 669 doStartNattKeepalive(); 670 final ArgumentCaptor<NattKeepalivePacketData> kpdCaptor = 671 ArgumentCaptor.forClass(NattKeepalivePacketData.class); 672 verify(mNai).onStartNattSocketKeepalive( 673 eq(TEST_SLOT), eq(TEST_KEEPALIVE_INTERVAL_SEC), kpdCaptor.capture()); 674 // Verify that address translation is not triggered so the addresses are still v4. 675 final NattKeepalivePacketData kpd = kpdCaptor.getValue(); 676 assertTrue(kpd.getSrcAddress() instanceof Inet4Address); 677 assertTrue(kpd.getDstAddress() instanceof Inet4Address); 678 } 679 680 @Test testStartNattKeepalive_addressTranslationOnClat()681 public void testStartNattKeepalive_addressTranslationOnClat() throws Exception { 682 final InetAddress v6AddrSrc = InetAddresses.parseNumericAddress("2001:db8::1"); 683 final InetAddress v6AddrDst = InetAddresses.parseNumericAddress("2001:db8::2"); 684 setupTestNaiForClat(v6AddrSrc, v6AddrDst); 685 686 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 687 final ArgumentCaptor<NattKeepalivePacketData> kpdCaptor = 688 ArgumentCaptor.forClass(NattKeepalivePacketData.class); 689 verify(mNai).onStartNattSocketKeepalive( 690 eq(TEST_SLOT), eq(TEST_KEEPALIVE_INTERVAL_SEC), kpdCaptor.capture()); 691 final NattKeepalivePacketData kpd = kpdCaptor.getValue(); 692 // Verify the addresses are updated to v6 when clat is started. 693 assertEquals(v6AddrSrc, kpd.getSrcAddress()); 694 assertEquals(v6AddrDst, kpd.getDstAddress()); 695 696 triggerEventKeepalive(TEST_SLOT, SocketKeepalive.SUCCESS); 697 verify(testInfo.socketKeepaliveCallback).onStarted(); 698 699 // Remove clat address should stop the keepalive. 700 doReturn(null).when(mNai).getClatv6SrcAddress(); 701 visibleOnHandlerThread( 702 mTestHandler, () -> mAOOKeepaliveTracker.handleCheckKeepalivesStillValid(mNai)); 703 checkAndProcessKeepaliveStop(); 704 assertNull(getAutoKiForBinder(testInfo.binder)); 705 706 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 707 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 708 } 709 710 @Test testHandleEventSocketKeepalive_startingFailureHardwareError()711 public void testHandleEventSocketKeepalive_startingFailureHardwareError() throws Exception { 712 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 713 714 verify(mNai).onStartNattSocketKeepalive( 715 TEST_SLOT, TEST_KEEPALIVE_INTERVAL_SEC, (NattKeepalivePacketData) testInfo.kpd); 716 verify(mNai).onAddNattKeepalivePacketFilter( 717 TEST_SLOT, (NattKeepalivePacketData) testInfo.kpd); 718 // Network agent returns an error, fails to start the keepalive. 719 triggerEventKeepalive(TEST_SLOT, SocketKeepalive.ERROR_HARDWARE_ERROR); 720 721 checkAndProcessKeepaliveStop(); 722 723 assertNull(getAutoKiForBinder(testInfo.binder)); 724 725 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_HARDWARE_ERROR); 726 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 727 } 728 729 @Test testHandleCheckKeepalivesStillValid_linkPropertiesChanged()730 public void testHandleCheckKeepalivesStillValid_linkPropertiesChanged() throws Exception { 731 // Successful start of NATT keepalive. 732 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 733 checkAndProcessKeepaliveStart(testInfo.kpd); 734 verify(testInfo.socketKeepaliveCallback).onStarted(); 735 736 // Source address is removed from link properties by clearing. 737 mNai.linkProperties.clear(); 738 739 // Check for valid keepalives 740 visibleOnHandlerThread( 741 mTestHandler, () -> mAOOKeepaliveTracker.handleCheckKeepalivesStillValid(mNai)); 742 743 checkAndProcessKeepaliveStop(); 744 745 assertNull(getAutoKiForBinder(testInfo.binder)); 746 747 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 748 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 749 } 750 751 @Test testStopKeepalive()752 public void testStopKeepalive() throws Exception { 753 // Successful start of NATT keepalive. 754 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 755 checkAndProcessKeepaliveStart(testInfo.kpd); 756 verify(testInfo.socketKeepaliveCallback).onStarted(); 757 758 doStopKeepalive(getAutoKiForBinder(testInfo.binder)); 759 checkAndProcessKeepaliveStop(); 760 761 assertNull(getAutoKiForBinder(testInfo.binder)); 762 verify(testInfo.socketKeepaliveCallback).onStopped(); 763 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 764 } 765 766 @Test testPauseKeepalive()767 public void testPauseKeepalive() throws Exception { 768 // Successful start of NATT keepalive. 769 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 770 checkAndProcessKeepaliveStart(testInfo.kpd); 771 verify(testInfo.socketKeepaliveCallback).onStarted(); 772 773 doPauseKeepalive(getAutoKiForBinder(testInfo.binder)); 774 775 checkAndProcessKeepaliveStop(); 776 verify(testInfo.socketKeepaliveCallback).onPaused(); 777 778 // Pausing does not cleanup the autoKi 779 assertNotNull(getAutoKiForBinder(testInfo.binder)); 780 781 clearInvocations(mNai); 782 doStopKeepalive(getAutoKiForBinder(testInfo.binder)); 783 // The keepalive is already stopped. 784 verify(mNai, never()).onStopSocketKeepalive(TEST_SLOT); 785 verify(mNai, never()).onRemoveKeepalivePacketFilter(TEST_SLOT); 786 787 // Stopping while paused still calls onStopped. 788 verify(testInfo.socketKeepaliveCallback).onStopped(); 789 // autoKi is cleaned up. 790 assertNull(getAutoKiForBinder(testInfo.binder)); 791 792 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 793 794 // Make sure the slot is free 795 final TestKeepaliveInfo testInfo2 = doStartNattKeepalive(); 796 checkAndProcessKeepaliveStart(testInfo2.kpd); 797 } 798 799 @Test testResumeKeepalive()800 public void testResumeKeepalive() throws Exception { 801 // Successful start of NATT keepalive. 802 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 803 checkAndProcessKeepaliveStart(testInfo.kpd); 804 verify(testInfo.socketKeepaliveCallback).onStarted(); 805 806 doPauseKeepalive(getAutoKiForBinder(testInfo.binder)); 807 checkAndProcessKeepaliveStop(); 808 verify(testInfo.socketKeepaliveCallback).onPaused(); 809 810 clearInvocations(mNai); 811 doResumeKeepalive(getAutoKiForBinder(testInfo.binder)); 812 checkAndProcessKeepaliveStart(testInfo.kpd); 813 assertNotNull(getAutoKiForBinder(testInfo.binder)); 814 verify(testInfo.socketKeepaliveCallback).onResumed(); 815 816 doStopKeepalive(getAutoKiForBinder(testInfo.binder)); 817 checkAndProcessKeepaliveStop(); 818 assertNull(getAutoKiForBinder(testInfo.binder)); 819 820 verify(testInfo.socketKeepaliveCallback).onStopped(); 821 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 822 } 823 824 @Test testResumeKeepalive_invalidSourceAddress()825 public void testResumeKeepalive_invalidSourceAddress() throws Exception { 826 // Successful start of NATT keepalive. 827 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 828 checkAndProcessKeepaliveStart(testInfo.kpd); 829 verify(testInfo.socketKeepaliveCallback).onStarted(); 830 831 doPauseKeepalive(getAutoKiForBinder(testInfo.binder)); 832 checkAndProcessKeepaliveStop(); 833 verify(testInfo.socketKeepaliveCallback).onPaused(); 834 835 mNai.linkProperties.clear(); 836 837 clearInvocations(mNai); 838 doResumeKeepalive(getAutoKiForBinder(testInfo.binder)); 839 verify(mNai, never()).onStartNattSocketKeepalive(anyInt(), anyInt(), any()); 840 verify(mNai, never()).onAddNattKeepalivePacketFilter(anyInt(), any()); 841 842 assertNull(getAutoKiForBinder(testInfo.binder)); 843 844 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 845 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 846 } 847 848 @Test testResumeKeepalive_startingFailureHardwareError()849 public void testResumeKeepalive_startingFailureHardwareError() throws Exception { 850 // Successful start of NATT keepalive. 851 final TestKeepaliveInfo testInfo = doStartNattKeepalive(); 852 checkAndProcessKeepaliveStart(testInfo.kpd); 853 verify(testInfo.socketKeepaliveCallback).onStarted(); 854 855 doPauseKeepalive(getAutoKiForBinder(testInfo.binder)); 856 checkAndProcessKeepaliveStop(); 857 verify(testInfo.socketKeepaliveCallback).onPaused(); 858 859 clearInvocations(mNai); 860 doResumeKeepalive(getAutoKiForBinder(testInfo.binder)); 861 862 verify(mNai).onStartNattSocketKeepalive( 863 TEST_SLOT, TEST_KEEPALIVE_INTERVAL_SEC, (NattKeepalivePacketData) testInfo.kpd); 864 verify(mNai).onAddNattKeepalivePacketFilter( 865 TEST_SLOT, (NattKeepalivePacketData) testInfo.kpd); 866 // Network agent returns error on starting the keepalive. 867 triggerEventKeepalive(TEST_SLOT, SocketKeepalive.ERROR_HARDWARE_ERROR); 868 869 checkAndProcessKeepaliveStop(); 870 871 assertNull(getAutoKiForBinder(testInfo.binder)); 872 verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_HARDWARE_ERROR); 873 verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback)); 874 } 875 876 @Test testStopAllKeepalives()877 public void testStopAllKeepalives() throws Exception { 878 final TestKeepaliveInfo testInfo1 = doStartNattKeepalive(); 879 final TestKeepaliveInfo testInfo2 = doStartNattKeepalive(); 880 checkAndProcessKeepaliveStart(TEST_SLOT, testInfo1.kpd); 881 checkAndProcessKeepaliveStart(TEST_SLOT + 1, testInfo2.kpd); 882 883 verify(testInfo1.socketKeepaliveCallback).onStarted(); 884 verify(testInfo2.socketKeepaliveCallback).onStarted(); 885 886 // Pause the first keepalive 887 doPauseKeepalive(getAutoKiForBinder(testInfo1.binder)); 888 checkAndProcessKeepaliveStop(TEST_SLOT); 889 verify(testInfo1.socketKeepaliveCallback).onPaused(); 890 891 visibleOnHandlerThread( 892 mTestHandler, 893 () -> mAOOKeepaliveTracker.handleStopAllKeepalives( 894 mNai, SocketKeepalive.ERROR_INVALID_NETWORK)); 895 896 // Note that checkAndProcessKeepaliveStop is not called since the network agent is assumed 897 // to be disconnected for a handleStopAllKeepalives call. 898 assertNull(getAutoKiForBinder(testInfo1.binder)); 899 assertNull(getAutoKiForBinder(testInfo2.binder)); 900 901 verify(testInfo1.socketKeepaliveCallback, never()).onStopped(); 902 verify(testInfo2.socketKeepaliveCallback, never()).onStopped(); 903 verify(testInfo1.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_NETWORK); 904 verify(testInfo2.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_NETWORK); 905 906 verifyNoMoreInteractions(ignoreStubs(testInfo1.socketKeepaliveCallback)); 907 verifyNoMoreInteractions(ignoreStubs(testInfo2.socketKeepaliveCallback)); 908 } 909 910 @Test testTwoKeepalives_startAfterPause()911 public void testTwoKeepalives_startAfterPause() throws Exception { 912 final TestKeepaliveInfo testInfo1 = doStartNattKeepalive(); 913 checkAndProcessKeepaliveStart(testInfo1.kpd); 914 verify(testInfo1.socketKeepaliveCallback).onStarted(); 915 assertNotNull(getAutoKiForBinder(testInfo1.binder)); 916 917 final AutomaticOnOffKeepalive autoKi1 = getAutoKiForBinder(testInfo1.binder); 918 doPauseKeepalive(autoKi1); 919 checkAndProcessKeepaliveStop(TEST_SLOT); 920 verify(testInfo1.socketKeepaliveCallback).onPaused(); 921 assertNotNull(getAutoKiForBinder(testInfo1.binder)); 922 923 clearInvocations(mNai); 924 // Start the second keepalive while the first is paused. 925 final TestKeepaliveInfo testInfo2 = doStartNattKeepalive(); 926 // The slot used is TEST_SLOT + 1 since TEST_SLOT is being taken by the paused keepalive. 927 checkAndProcessKeepaliveStart(TEST_SLOT + 1, testInfo2.kpd); 928 verify(testInfo2.socketKeepaliveCallback).onStarted(); 929 assertNotNull(getAutoKiForBinder(testInfo2.binder)); 930 931 clearInvocations(mNai); 932 doResumeKeepalive(autoKi1); 933 // Resume on TEST_SLOT. 934 checkAndProcessKeepaliveStart(TEST_SLOT, testInfo1.kpd); 935 verify(testInfo1.socketKeepaliveCallback).onResumed(); 936 937 clearInvocations(mNai); 938 doStopKeepalive(autoKi1); 939 checkAndProcessKeepaliveStop(TEST_SLOT); 940 verify(testInfo1.socketKeepaliveCallback).onStopped(); 941 verify(testInfo2.socketKeepaliveCallback, never()).onStopped(); 942 assertNull(getAutoKiForBinder(testInfo1.binder)); 943 944 clearInvocations(mNai); 945 assertNotNull(getAutoKiForBinder(testInfo2.binder)); 946 doStopKeepalive(getAutoKiForBinder(testInfo2.binder)); 947 checkAndProcessKeepaliveStop(TEST_SLOT + 1); 948 verify(testInfo2.socketKeepaliveCallback).onStopped(); 949 assertNull(getAutoKiForBinder(testInfo2.binder)); 950 951 verifyNoMoreInteractions(ignoreStubs(testInfo1.socketKeepaliveCallback)); 952 verifyNoMoreInteractions(ignoreStubs(testInfo2.socketKeepaliveCallback)); 953 } 954 955 @Test testStartTcpKeepalive_fdInitiatedStop()956 public void testStartTcpKeepalive_fdInitiatedStop() throws Exception { 957 final InetAddress srcAddress = InetAddress.getByAddress( 958 new byte[] { (byte) 192, 0, 0, (byte) 129 }); 959 mNai.linkProperties.addLinkAddress(new LinkAddress(srcAddress, 24)); 960 961 final TestKeepaliveInfo testInfo = 962 doStartTcpKeepalive(InetAddress.getByAddress(V4_SRC_ADDR)); 963 964 // A closed socket will result in EVENT_HANGUP and trigger error to 965 // FileDescriptorEventListener. 966 testInfo.socket.close(); 967 HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS); 968 969 // The keepalive should be removed in AutomaticOnOffKeepaliveTracker. 970 assertNull(getAutoKiForBinder(testInfo.binder)); 971 } 972 973 @Test testDumpDoesNotCrash()974 public void testDumpDoesNotCrash() throws Exception { 975 final TestKeepaliveInfo testInfo1 = doStartNattKeepalive(); 976 final TestKeepaliveInfo testInfo2 = doStartNattKeepalive(); 977 checkAndProcessKeepaliveStart(TEST_SLOT, testInfo1.kpd); 978 checkAndProcessKeepaliveStart(TEST_SLOT + 1, testInfo2.kpd); 979 final AutomaticOnOffKeepalive autoKi1 = getAutoKiForBinder(testInfo1.binder); 980 doPauseKeepalive(autoKi1); 981 982 final StringWriter stringWriter = new StringWriter(); 983 final IndentingPrintWriter pw = new IndentingPrintWriter(stringWriter, " "); 984 visibleOnHandlerThread(mTestHandler, () -> mAOOKeepaliveTracker.dump(pw)); 985 assertFalse(stringWriter.toString().isEmpty()); 986 } 987 } 988