blob: 5960e00a4f09e8b3aa91968df17b1452115e8eb7 [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.iwlan.epdg;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.InetAddresses;
import android.net.LinkAddress;
import android.net.Network;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionParams;
import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.SaProposal;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer;
import android.net.ipsec.ike.ike3gpp.Ike3gppData;
import android.net.ipsec.ike.ike3gpp.Ike3gppExtension;
import android.os.PersistableBundle;
import android.os.test.TestLooper;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import com.google.android.iwlan.IwlanError;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.internal.util.reflection.FieldSetter;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
@RunWith(JUnit4.class)
public class EpdgTunnelManagerTest {
public static final int DEFAULT_SLOT_INDEX = 0;
public static final int DEFAULT_SUBID = 0;
private static final String TEST_IP_ADDRESS = "127.0.0.1";
private static final String TEST_APN_NAME = "www.xyz.com";
private static final ArrayList<InetAddress> EXPECTED_EPDG_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {
InetAddresses.parseNumericAddress(TEST_IP_ADDRESS)
}));
private EpdgTunnelManager mEpdgTunnelManager;
private class IwlanTunnelCallback implements EpdgTunnelManager.TunnelCallback {
public void onOpened(String apnName, TunnelLinkProperties linkProperties) {}
public void onClosed(String apnName, IwlanError error) {}
}
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
private TestLooper mTestLooper = new TestLooper();
@Mock private Context mMockContext;
@Mock private IwlanTunnelCallback mMockIwlanTunnelCallback;
@Mock private IkeSession mMockIkeSession;
@Mock private EpdgSelector mMockEpdgSelector;
@Mock private Network mMockNetwork;
@Mock CarrierConfigManager mMockCarrierConfigManager;
@Mock SubscriptionManager mMockSubscriptionManager;
@Mock SubscriptionInfo mMockSubscriptionInfo;
@Mock TelephonyManager mMockTelephonyManager;
@Mock EpdgTunnelManager.IkeSessionCreator mMockIkeSessionCreator;
@Mock IkeException mMockIkeException;
@Mock IkeSessionConfiguration mMockIkeSessionConfiguration;
@Before
public void setUp() throws Exception {
mEpdgTunnelManager = spy(EpdgTunnelManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX));
doReturn(mTestLooper.getLooper()).when(mEpdgTunnelManager).getLooper();
setVariable(mEpdgTunnelManager, "mContext", mMockContext);
mEpdgTunnelManager.initHandler();
mEpdgTunnelManager.resetTunnelManagerState();
when(mEpdgTunnelManager.getEpdgSelector()).thenReturn(mMockEpdgSelector);
when(mEpdgTunnelManager.getIkeSessionCreator()).thenReturn(mMockIkeSessionCreator);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
anyBoolean(),
anyBoolean(),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
// initialize carrier configuration
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
// Fake local address
List<InetAddress> testLocalAddressList = new ArrayList<InetAddress>();
InetAddress testInetaddr = InetAddress.getByName(TEST_IP_ADDRESS);
testLocalAddressList.add(testInetaddr);
doReturn(testLocalAddressList).when(mEpdgTunnelManager).getAddressForNetwork(any(), any());
}
@Test
public void testBringUpTunnelWithInvalidProtocol() {
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_PPP),
mMockIwlanTunnelCallback);
assertFalse(ret);
}
@Test
public void testBringUpTunnelWithInvalidPduSessionId() {
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6, 16),
mMockIwlanTunnelCallback);
assertFalse(ret);
ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6, -1),
mMockIwlanTunnelCallback);
assertFalse(ret);
}
@Test
public void testBringUpTunnelWithValidProtocols() {
String testApnName1 = "www.xyz.com1";
String testApnName2 = "www.xyz.com2";
String testApnName3 = "www.xyz.com3";
TunnelSetupRequest TSR_v4 =
getBasicTunnelSetupRequest(testApnName1, ApnSetting.PROTOCOL_IP);
TunnelSetupRequest TSR_v6 =
getBasicTunnelSetupRequest(testApnName2, ApnSetting.PROTOCOL_IPV6);
TunnelSetupRequest TSR_v4v6 =
getBasicTunnelSetupRequest(testApnName3, ApnSetting.PROTOCOL_IPV4V6);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName1));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName2));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName3));
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR_v4, mMockIwlanTunnelCallback);
assertTrue(ret);
ret = mEpdgTunnelManager.bringUpTunnel(TSR_v6, mMockIwlanTunnelCallback);
assertTrue(ret);
ret = mEpdgTunnelManager.bringUpTunnel(TSR_v4v6, mMockIwlanTunnelCallback);
assertTrue(ret);
}
@Test
public void testBringUpTunnelWithNullApn() {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
when(mEpdgTunnelManager.getTunnelSetupRequestApnName(TSR)).thenReturn(null);
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR, mMockIwlanTunnelCallback);
assertFalse(ret);
verify(mEpdgTunnelManager).getTunnelSetupRequestApnName(TSR);
}
@Test
public void testBringUpTunnelWithExistApn() {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
when(mEpdgTunnelManager.isTunnelConfigContainExistApn(TEST_APN_NAME)).thenReturn(true);
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR, mMockIwlanTunnelCallback);
assertFalse(ret);
verify(mEpdgTunnelManager).isTunnelConfigContainExistApn(TEST_APN_NAME);
}
@Test
public void testBringUPTunnelWithNoBringUpInProcess() {
String testApnName2 = "www.abc.com";
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName2, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR, mMockIwlanTunnelCallback);
assertTrue(ret);
}
@Test
public void testBringUPTunnelSuccess() throws Exception {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR, mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
private void setupTunnelBringup() throws Exception {
setupMockForGetConfig(null);
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
}
@Test
public void testBringUpTunnelSetsDeviceIdentityImeiSv() throws Exception {
when(mMockContext.getSystemService(eq(TelephonyManager.class)))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID))
.thenReturn(mMockTelephonyManager);
String TEST_IMEI = "012345678901234";
String TEST_IMEI_SUFFIX = "56";
String EXPECTED_IMEISV = TEST_IMEI.substring(0, TEST_IMEI.length() - 1) + TEST_IMEI_SUFFIX;
when(mMockTelephonyManager.getImei()).thenReturn(TEST_IMEI);
when(mMockTelephonyManager.getDeviceSoftwareVersion()).thenReturn(TEST_IMEI_SUFFIX);
setupTunnelBringup();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(
ikeSessionParams.getIke3gppExtension().getIke3gppParams().getMobileDeviceIdentity(),
EXPECTED_IMEISV);
}
@Test
public void testBringUpTunnelSetsDeviceIdentityImei() throws Exception {
when(mMockContext.getSystemService(eq(TelephonyManager.class)))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID))
.thenReturn(mMockTelephonyManager);
String TEST_IMEI = "012345678901234";
when(mMockTelephonyManager.getImei()).thenReturn(TEST_IMEI);
when(mMockTelephonyManager.getDeviceSoftwareVersion()).thenReturn(null);
setupTunnelBringup();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(
ikeSessionParams.getIke3gppExtension().getIke3gppParams().getMobileDeviceIdentity(),
TEST_IMEI);
}
@Test
public void testBringUpTunnelNoDeviceIdentityWhenImeiUnavailable() throws Exception {
when(mMockContext.getSystemService(eq(TelephonyManager.class)))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.getImei()).thenReturn(null);
setupTunnelBringup();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(
ikeSessionParams.getIke3gppExtension().getIke3gppParams().getMobileDeviceIdentity(),
null);
}
@Test
public void testBringUpTunnelWithMobilityOptions() throws Exception {
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertTrue(ikeSessionParams.hasIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE));
assertTrue(ikeSessionParams.hasIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY));
}
@Test
public void testCloseTunnelWithNoTunnelForApn() throws Exception {
String testApnName = "www.xyz.com";
boolean ret = mEpdgTunnelManager.closeTunnel(testApnName, false /*forceClose*/);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager).closePendingRequestsForApn(eq(testApnName));
}
@Test
public void testCloseTunnelWithForceClose() throws Exception {
String testApnName = "www.xyz.com";
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
boolean ret = mEpdgTunnelManager.closeTunnel(testApnName, true /*forceClose*/);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockIkeSession).kill();
verify(mEpdgTunnelManager).closePendingRequestsForApn(eq(testApnName));
}
@Test
public void testCloseTunnelWithNonForceClose() throws Exception {
String testApnName = "www.xyz.com";
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
boolean ret = mEpdgTunnelManager.closeTunnel(testApnName, false /*forceClose*/);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockIkeSession).close();
verify(mEpdgTunnelManager).closePendingRequestsForApn(eq(testApnName));
}
@Test
public void testRekeyAndNattTimerFromCarrierConfig() throws Exception {
String testApnName = "www.xyz.com";
// Test values
int hardTime = 50000;
int softTime = 20000;
int hardTimeChild = 10000;
int softTimeChild = 1000;
int nattTimer = 60;
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT, hardTime);
bundle.putInt(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, softTime);
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, hardTimeChild);
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, softTimeChild);
bundle.putInt(CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, nattTimer);
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<ChildSessionParams> childSessionParamsCaptor =
ArgumentCaptor.forClass(ChildSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
childSessionParamsCaptor.capture(),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
ChildSessionParams childSessionParams = childSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getHardLifetimeSeconds(), hardTime);
assertEquals(ikeSessionParams.getSoftLifetimeSeconds(), softTime);
assertEquals(childSessionParams.getHardLifetimeSeconds(), hardTimeChild);
assertEquals(childSessionParams.getSoftLifetimeSeconds(), softTimeChild);
assertEquals(ikeSessionParams.getNattKeepAliveDelaySeconds(), nattTimer);
}
@Test
public void testSetRetransmissionTimeoutsFromCarrierConfig() throws Exception {
String testApnName = "www.xyz.com";
int[] testTimeouts = {1000, 1200, 1400, 1600, 2000, 4000};
PersistableBundle bundle = new PersistableBundle();
bundle.putIntArray(
CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY, testTimeouts);
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertArrayEquals(ikeSessionParams.getRetransmissionTimeoutsMillis(), testTimeouts);
}
@Test
public void testSetDpdDelayFromCarrierConfig() throws Exception {
String testApnName = "www.xyz.com";
// Test values
int testDpdDelay = 600;
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT, testDpdDelay);
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getDpdDelaySeconds(), testDpdDelay);
}
@Test
public void testGetValidEpdgAddress_DiffAddr() throws Exception {
String testApnName = "www.xyz.com";
List<InetAddress> ipList1 = new ArrayList<>();
ipList1.add(InetAddress.getByName("1.1.1.1"));
mEpdgTunnelManager.validateAndSetEpdgAddress(ipList1);
IwlanError error = new IwlanError(new IkeInternalException(new IOException()));
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
setupMockForGetConfig(null);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList2 = new ArrayList<>();
ipList2.add(InetAddress.getByName("8.8.8.8"));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList2, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
EpdgTunnelManager.TmIkeSessionCallback ikeSessionCallback =
verifyCreateIkeSession(ipList2.get(0));
ikeSessionCallback.onClosedExceptionally(
new IkeInternalException(new IOException("Retransmitting failure")));
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
@Test
public void testGetValidEpdgAddress_NextAddr() throws Exception {
String testApnName = "www.xyz.com";
List<InetAddress> ipList1 = new ArrayList<>();
ipList1.add(InetAddress.getByName("1.1.1.1"));
ipList1.add(InetAddress.getByName("8.8.8.8"));
mEpdgTunnelManager.validateAndSetEpdgAddress(ipList1);
IwlanError error = new IwlanError(new IkeInternalException(new IOException()));
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
setupMockForGetConfig(null);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList2 = new ArrayList<>();
ipList2.add(InetAddress.getByName("1.1.1.1"));
ipList2.add(InetAddress.getByName("8.8.8.8"));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList2, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
EpdgTunnelManager.TmIkeSessionCallback ikeSessionCallback =
verifyCreateIkeSession(ipList2.get(1));
ikeSessionCallback.onClosedExceptionally(
new IkeInternalException(new IOException("Retransmitting failure")));
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
private EpdgTunnelManager.TmIkeSessionCallback verifyCreateIkeSession(InetAddress ip)
throws Exception {
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<EpdgTunnelManager.TmIkeSessionCallback> ikeSessionCallbackCaptor =
ArgumentCaptor.forClass(EpdgTunnelManager.TmIkeSessionCallback.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
ikeSessionCallbackCaptor.capture(),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getServerHostname(), ip.getHostAddress());
return ikeSessionCallbackCaptor.getValue();
}
@Test
public void testIpv6PrefixMatching() throws Exception {
InetAddress a1 = InetAddress.getByName("2600:381:4872:5d1e:ac45:69c7:bab2:639b");
LinkAddress l1 = new LinkAddress(a1, 64);
InetAddress src = InetAddress.getByName("2600:381:4872:5d1e:0:10:3582:a501");
EpdgTunnelManager.TunnelConfig tf =
mEpdgTunnelManager.new TunnelConfig(null, null, src, 64);
assertTrue(tf.isPrefixSameAsSrcIP(l1));
// different prefix length
LinkAddress l2 = new LinkAddress(a1, 63);
assertFalse(tf.isPrefixSameAsSrcIP(l2));
}
@Test
public void testBackOffTimeCalculation() throws Exception {
int transactionId = 1;
// unit: 10 mins value: 2 expectedTime: 1200 (10 * 60 * 2)
verifyBackOffTimer("00000010", 1200, transactionId++);
// unit: 1 hour value: 4 expectedTime: 14400 (1 * 60 * 60 * 4)
verifyBackOffTimer("00100100", 14400, transactionId++);
// unit: 10 hours value: 3 expectedTime: (10 * 60 * 60 * 3)
verifyBackOffTimer("01000011", 108000, transactionId++);
// unit: 2 secs value: 21 expectedTime: 42 (2 * 21)
verifyBackOffTimer("01110101", 42, transactionId++);
// unit: 30 secs value: 31 expectedTime: 930 (30 * 31)
verifyBackOffTimer("10011111", 930, transactionId++);
// unit: 1 min value: 25 expectedTime: 1500 (1 * 60 * 25)
verifyBackOffTimer("10111001", 1500, transactionId++);
// unit: 1 hour value: 12 expectedTime: 43200 (1 * 60 * 60 * 12)
verifyBackOffTimer("11001100", 43200, transactionId++);
// deactivate - Should not report backoff time.
verifyBackOffTimer("11100100", -1, transactionId++);
}
private void verifyBackOffTimer(String backoffByte, long expectedBackoffTime, int transactionId)
throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(new IkeInternalException(new Exception()));
Ike3gppBackoffTimer mockIke3gppBackoffTimer = mock(Ike3gppBackoffTimer.class);
List<Ike3gppData> ike3gppInfoList = new ArrayList<>();
ike3gppInfoList.add(mockIke3gppBackoffTimer);
doReturn(Ike3gppData.DATA_TYPE_NOTIFY_BACKOFF_TIMER)
.when(mockIke3gppBackoffTimer)
.getDataType();
doReturn((byte) (int) Integer.parseInt(backoffByte, 2))
.when(mockIke3gppBackoffTimer)
.getBackoffTimer();
// if back off time expected is negative normal reportIwlanError should be called.
if (expectedBackoffTime < 0) {
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
} else {
doReturn(0L)
.when(mEpdgTunnelManager)
.reportIwlanError(eq(testApnName), eq(error), anyLong());
}
setupMockForGetConfig(null);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName("1.1.1.1"));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), transactionId);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<EpdgTunnelManager.TmIkeSessionCallback> ikeSessionCallbackCaptor =
ArgumentCaptor.forClass(EpdgTunnelManager.TmIkeSessionCallback.class);
verify(mMockIkeSessionCreator, atLeastOnce())
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
ikeSessionCallbackCaptor.capture(),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getServerHostname(), ipList.get(0).getHostAddress());
Ike3gppExtension.Ike3gppDataListener ike3gppCallback =
ikeSessionParams.getIke3gppExtension().getIke3gppDataListener();
ike3gppCallback.onIke3gppDataReceived(ike3gppInfoList);
EpdgTunnelManager.TmIkeSessionCallback ikeSessionCallback =
ikeSessionCallbackCaptor.getValue();
ikeSessionCallback.onClosedExceptionally(new IkeInternalException(new Exception()));
mTestLooper.dispatchAll();
// if expected backoff time is negative - verify that backoff time is not reported.
if (expectedBackoffTime < 0) {
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
} else {
// Else - Verify reportIwlanError with correct backoff time is being called.
verify(mEpdgTunnelManager, times(1))
.reportIwlanError(eq(testApnName), eq(error), eq(expectedBackoffTime));
}
verify(mMockIwlanTunnelCallback, atLeastOnce()).onClosed(eq(testApnName), eq(error));
}
private TunnelSetupRequest getBasicTunnelSetupRequest(String apnName, int apnIpProtocol) {
return getBasicTunnelSetupRequest(apnName, apnIpProtocol, 1);
}
private TunnelSetupRequest getBasicTunnelSetupRequest(
String apnName, int apnIpProtocol, int pduSessionId) {
TunnelSetupRequest ret =
TunnelSetupRequest.builder()
.setApnName(apnName)
.setNetwork(mMockNetwork)
.setIsRoaming(false /*isRoaming*/)
.setIsEmergency(false /*IsEmergency*/)
.setRequestPcscf(false /*requestPcscf*/)
.setApnIpProtocol(apnIpProtocol)
.setPduSessionId(pduSessionId)
.build();
return ret;
}
private TunnelSetupRequest getHandoverTunnelSetupRequest(String apnName, int apnIpProtocol) {
TunnelSetupRequest.Builder bld = TunnelSetupRequest.builder();
bld.setApnName(apnName)
.setNetwork(mMockNetwork)
.setIsRoaming(false /*isRoaming*/)
.setIsEmergency(false /*IsEmergency*/)
.setRequestPcscf(false /*requestPcscf*/)
.setApnIpProtocol(apnIpProtocol)
.setPduSessionId(1);
switch (apnIpProtocol) {
case ApnSetting.PROTOCOL_IP:
bld.setSrcIpv4Address(InetAddresses.parseNumericAddress("10.10.10.10"));
break;
case ApnSetting.PROTOCOL_IPV6:
bld.setSrcIpv6Address(
InetAddresses.parseNumericAddress(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
break;
case ApnSetting.PROTOCOL_IPV4V6:
bld.setSrcIpv4Address(InetAddresses.parseNumericAddress("10.10.10.10"));
bld.setSrcIpv6Address(
InetAddresses.parseNumericAddress(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
break;
}
return bld.build();
}
private void setupMockForGetConfig(PersistableBundle bundle) {
if (bundle == null) {
bundle = new PersistableBundle();
}
bundle.putIntArray(
CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
new int[] {
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256,
});
when(mMockContext.getSystemService(eq(CarrierConfigManager.class)))
.thenReturn(mMockCarrierConfigManager);
when(mMockContext.getSystemService(eq(SubscriptionManager.class)))
.thenReturn(mMockSubscriptionManager);
when(mMockContext.getSystemService(eq(TelephonyManager.class)))
.thenReturn(mMockTelephonyManager);
when(mMockSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(DEFAULT_SLOT_INDEX))
.thenReturn(mMockSubscriptionInfo);
when(mMockSubscriptionInfo.getSubscriptionId()).thenReturn(DEFAULT_SUBID);
when(mMockSubscriptionInfo.getMncString()).thenReturn("344");
when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID))
.thenReturn(mMockTelephonyManager);
when(mMockCarrierConfigManager.getConfigForSubId(DEFAULT_SLOT_INDEX)).thenReturn(bundle);
}
private void setVariable(Object target, String variableName, Object value) throws Exception {
FieldSetter.setField(target, target.getClass().getDeclaredField(variableName), value);
}
@Test
public void testHandleOnClosedWithEpdgAddressSelected_True() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(IwlanError.NETWORK_FAILURE);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
mEpdgTunnelManager.getTmIkeSessionCallback(testApnName).onClosed();
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
verify(mEpdgTunnelManager, times(2)).resetTunnelManagerState();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testHandleOnClosedWithEpdgAddressSelected_False() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(IwlanError.NETWORK_FAILURE);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setIsEpdgAddressSelected(false);
mEpdgTunnelManager.getTmIkeSessionCallback(testApnName).onClosed();
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
verify(mEpdgTunnelManager, times(2)).resetTunnelManagerState();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testHandleOnClosedExceptionallyWithEpdgAddressSelected_True() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(mMockIkeException);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName)
.onClosedExceptionally(mMockIkeException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
verify(mEpdgTunnelManager, times(2)).resetTunnelManagerState();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testHandleOnClosedExceptionallyWithEpdgAddressSelected_False() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(mMockIkeException);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setIsEpdgAddressSelected(false);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName)
.onClosedExceptionally(mMockIkeException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), any(IwlanError.class));
verify(mEpdgTunnelManager, times(2)).resetTunnelManagerState();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testIkeSessionOnOpenedUpdatesPcscfAddrInTunnelConfig() throws Exception {
String testApnName = "ims";
IwlanError error = new IwlanError(IwlanError.NO_ERROR);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
List<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
when(mMockIkeSessionConfiguration.getPcscfServers()).thenReturn(ipList);
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName)
.onOpened(mMockIkeSessionConfiguration);
mTestLooper.dispatchAll();
EpdgTunnelManager.TunnelConfig testApnTunnelConfig =
mEpdgTunnelManager.getTunnelConfigForApn(testApnName);
assertEquals(testApnTunnelConfig.getPcscfAddrList(), ipList);
}
@Test
public void testSetIkeTrafficSelectorsIPv4() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IP, false);
}
@Test
public void testSetIkeTrafficSelectorsIPv6() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IPV6, false);
}
@Test
public void testSetIkeTrafficSelectorsIPv4v6() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IPV4V6, false);
}
@Test
public void testSetIkeTrafficSelectorsIPv4_handover() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IP, true);
}
@Test
public void testSetIkeTrafficSelectorsIPv6_handover() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IPV6, true);
}
@Test
public void testSetIkeTrafficSelectorsIPv4v6_handover() throws Exception {
testSetIkeTrafficSelectors(ApnSetting.PROTOCOL_IPV4V6, true);
}
private void testSetIkeTrafficSelectors(int apnProtocol, boolean handover) throws Exception {
String testApnName = "www.xyz.com";
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret;
if (handover) {
ret =
mEpdgTunnelManager.bringUpTunnel(
getHandoverTunnelSetupRequest(TEST_APN_NAME, apnProtocol),
mMockIwlanTunnelCallback);
} else {
ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, apnProtocol),
mMockIwlanTunnelCallback);
}
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<ChildSessionParams> childSessionParamsCaptor =
ArgumentCaptor.forClass(ChildSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
childSessionParamsCaptor.capture(),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
ChildSessionParams childSessionParams = childSessionParamsCaptor.getValue();
switch (apnProtocol) {
case ApnSetting.PROTOCOL_IPV4V6:
assertEquals(childSessionParams.getInboundTrafficSelectors().size(), 2);
assertEquals(childSessionParams.getOutboundTrafficSelectors().size(), 2);
assertTrue(
childSessionParams.getInboundTrafficSelectors().get(0).endingAddress
!= childSessionParams
.getInboundTrafficSelectors()
.get(1)
.endingAddress);
assertTrue(
childSessionParams.getInboundTrafficSelectors().get(0).startingAddress
!= childSessionParams
.getInboundTrafficSelectors()
.get(1)
.startingAddress);
break;
case ApnSetting.PROTOCOL_IPV6:
assertEquals(childSessionParams.getInboundTrafficSelectors().size(), 1);
assertEquals(childSessionParams.getOutboundTrafficSelectors().size(), 1);
assertEquals(
childSessionParams.getOutboundTrafficSelectors().get(0),
childSessionParams.getInboundTrafficSelectors().get(0));
assertEquals(
childSessionParams.getInboundTrafficSelectors().get(0).endingAddress,
InetAddresses.parseNumericAddress(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
assertEquals(
childSessionParams.getInboundTrafficSelectors().get(0).startingAddress,
InetAddresses.parseNumericAddress("::"));
break;
case ApnSetting.PROTOCOL_IP:
assertEquals(childSessionParams.getInboundTrafficSelectors().size(), 1);
assertEquals(childSessionParams.getOutboundTrafficSelectors().size(), 1);
assertEquals(
childSessionParams.getOutboundTrafficSelectors().get(0),
childSessionParams.getInboundTrafficSelectors().get(0));
assertEquals(
childSessionParams.getInboundTrafficSelectors().get(0).endingAddress,
InetAddresses.parseNumericAddress("255.255.255.255"));
assertEquals(
childSessionParams.getInboundTrafficSelectors().get(0).startingAddress,
InetAddresses.parseNumericAddress("0.0.0.0"));
break;
}
}
@Test
public void testN1modeCapabilityInclusion() throws Exception {
{
testN1modeCapability(8);
}
}
@Test
public void testN1modeCapabilityNonInclusion() throws Exception {
{
testN1modeCapability(0);
}
}
@Test
public void testReportIwlanErrorIkeProtocolException() throws Exception {
String testApnName = "www.xyz.com";
IkeProtocolException mockException = mock(IkeProtocolException.class);
doReturn(IkeProtocolException.ERROR_TYPE_INVALID_IKE_SPI)
.when(mockException)
.getErrorType();
doReturn(new byte[0]).when(mockException).getErrorData();
IwlanError error = new IwlanError(mockException);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName)
.onClosedExceptionally(mockException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
verify(mEpdgTunnelManager, times(2)).resetTunnelManagerState();
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testReportIwlanErrorServerSelectionFailed() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(null, error, 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setIsEpdgAddressSelected(false);
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testCanBringUpTunnel() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(mMockIkeException);
doReturn(false).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
doReturn(error).when(mEpdgTunnelManager).getLastError(eq(testApnName));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
private void testN1modeCapability(int pduSessionId) throws Exception {
String testApnName = "www.xyz.com";
int PDU_SESSION_ID = pduSessionId;
byte PDU_SESSION_ID_BYTE = (byte) PDU_SESSION_ID;
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret;
ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(
TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6, PDU_SESSION_ID),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<ChildSessionParams> childSessionParamsCaptor =
ArgumentCaptor.forClass(ChildSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
childSessionParamsCaptor.capture(),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
if (pduSessionId == 0) {
assertNull(ikeSessionParams.getIke3gppExtension());
} else {
byte pduSessionIdByte =
ikeSessionParams.getIke3gppExtension().getIke3gppParams().getPduSessionId();
assertEquals(pduSessionIdByte, PDU_SESSION_ID_BYTE);
}
}
@Test
public void testInvalidNattTimerFromCarrierConfig() throws Exception {
String testApnName = "www.xyz.com";
int nattTimer = 4500; // valid range for natt timer is 0-3600
int ikeDefaultNattTimerValue = 20; // default value for natt timer is 20 secs
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, nattTimer);
setupMockForGetConfig(bundle);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getNattKeepAliveDelaySeconds(), ikeDefaultNattTimerValue);
}
@Test
public void testTunnelSetupRequestParams() throws Exception {
String testApnName = "www.xyz.com";
Inet6Address testAddressV6 = Inet6Address.getByAddress("25.25.25.25", new byte[16], 0);
Inet4Address testAddressV4 = (Inet4Address) Inet4Address.getByName("30.30.30.30");
int pduSessionId = 5;
boolean isRoaming = false;
boolean isEmergency = true;
boolean requestPcscf = true;
int ipv6AddressLen = 64;
TunnelSetupRequest tsr =
TunnelSetupRequest.builder()
.setApnName(testApnName)
.setNetwork(mMockNetwork)
.setApnIpProtocol(ApnSetting.PROTOCOL_IPV4V6)
.setSrcIpv6Address(testAddressV6)
.setSrcIpv6AddressPrefixLength(ipv6AddressLen)
.setSrcIpv4Address(testAddressV4)
.setPduSessionId(pduSessionId)
.setIsRoaming(isRoaming)
.setIsEmergency(isEmergency)
.setRequestPcscf(requestPcscf)
.build();
setupMockForGetConfig(null);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
anyInt(),
eq(isRoaming),
eq(isEmergency),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class)))
.thenReturn(new IwlanError(IwlanError.NO_ERROR));
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
any(IkeSessionParams.class),
any(ChildSessionParams.class),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
boolean ret = mEpdgTunnelManager.bringUpTunnel(tsr, mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
// verify isRoaming, isEmergency and Network variables.
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
anyInt(), // only Ipv6 address is added
eq(isRoaming),
eq(isEmergency),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class));
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<TunnelModeChildSessionParams> childSessionParamsCaptor =
ArgumentCaptor.forClass(TunnelModeChildSessionParams.class);
verify(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionParamsCaptor.capture(),
childSessionParamsCaptor.capture(),
any(Executor.class),
any(IkeSessionCallback.class),
any(ChildSessionCallback.class));
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
TunnelModeChildSessionParams childSessionParams = childSessionParamsCaptor.getValue();
// apnName verification. By default remote identification is type fqdn
IkeFqdnIdentification ikeId =
(IkeFqdnIdentification) ikeSessionParams.getRemoteIdentification();
assertEquals(ikeId.fqdn, testApnName);
// verify Network
assertEquals(ikeSessionParams.getNetwork(), mMockNetwork);
// verify requestPcscf (true) with Apn protocol IPV6
// it should add the pcscf config requests of type ConfigRequestIpv6PcscfServer and
// ConfigRequestIpv4PcscfServer
assertTrue(
ikeSessionParams.getConfigurationRequests().stream()
.anyMatch(c -> c instanceof IkeSessionParams.ConfigRequestIpv6PcscfServer));
assertTrue(
ikeSessionParams.getConfigurationRequests().stream()
.anyMatch(c -> c instanceof IkeSessionParams.ConfigRequestIpv4PcscfServer));
// verify pduSessionID
assertEquals(
ikeSessionParams.getIke3gppExtension().getIke3gppParams().getPduSessionId(),
pduSessionId);
// verify src ipv6 and src ipv4 address
List<TunnelModeChildSessionParams.TunnelModeChildConfigRequest> configRequests =
childSessionParams.getConfigurationRequests();
boolean ipv6ConfigRequestPresent = false;
boolean ipv4ConfigRequestPresent = true;
for (TunnelModeChildSessionParams.TunnelModeChildConfigRequest configRequest :
configRequests) {
if (configRequest instanceof TunnelModeChildSessionParams.ConfigRequestIpv6Address) {
ipv6ConfigRequestPresent = true;
assertEquals(
((TunnelModeChildSessionParams.ConfigRequestIpv6Address) configRequest)
.getAddress(),
testAddressV6);
assertEquals(
((TunnelModeChildSessionParams.ConfigRequestIpv6Address) configRequest)
.getPrefixLength(),
ipv6AddressLen);
}
if (configRequest instanceof TunnelModeChildSessionParams.ConfigRequestIpv4Address) {
ipv4ConfigRequestPresent = true;
assertEquals(
((TunnelModeChildSessionParams.ConfigRequestIpv4Address) configRequest)
.getAddress(),
testAddressV4);
}
}
assertTrue(ipv6ConfigRequestPresent);
assertTrue(ipv4ConfigRequestPresent);
}
@Test
public void testBringupTunnelFailWithInvalidSimState() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
when(mMockSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(DEFAULT_SLOT_INDEX))
.thenReturn(null);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
@Test
public void testBringupTunnelFailWithInvalidNai() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
PersistableBundle bundle = new PersistableBundle();
setupMockForGetConfig(bundle);
when(mMockSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(DEFAULT_SLOT_INDEX))
.thenReturn(mMockSubscriptionInfo)
.thenReturn(null);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback);
assertTrue(ret);
mTestLooper.dispatchAll();
ArrayList<InetAddress> ipList = new ArrayList<>();
ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
mEpdgTunnelManager.sendSelectionRequestComplete(
ipList, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
}