blob: 9ae512e5452653149a6ca020736ee17d380c1e66 [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.assertNotNull;
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.ConnectivityManager;
import android.net.InetAddresses;
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
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.IkeSessionConnectionInfo;
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 com.google.android.iwlan.IwlanTunnelMetricsImpl;
import com.google.android.iwlan.TunnelMetricsInterface.OnClosedMetrics;
import org.junit.Before;
import org.junit.Ignore;
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;
public static final int DEFAULT_TOKEN = 0;
private static final String EPDG_ADDRESS = "127.0.0.1";
private static final String TEST_APN_NAME = "www.xyz.com";
private static final ArrayList<InetAddress> EXPECTED_LOCAL_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {InetAddresses.parseNumericAddress("201.1.100.10")}));
private static final ArrayList<InetAddress> EXPECTED_IPV6_LOCAL_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {
InetAddresses.parseNumericAddress("2001:db8::1:2")
}));
private static final ArrayList<InetAddress> EXPECTED_EPDG_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {InetAddresses.parseNumericAddress(EPDG_ADDRESS)}));
private static final ArrayList<LinkAddress> EXPECTED_INTERNAL_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new LinkAddress[] {
new LinkAddress(
InetAddresses.parseNumericAddress("198.50.100.10"), 24)
}));
private static final ArrayList<InetAddress> EXPECTED_PCSCF_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {
InetAddresses.parseNumericAddress("198.51.100.10")
}));
private static final ArrayList<InetAddress> EXPECTED_DNS_ADDRESSES =
new ArrayList<>(
Arrays.asList(
new InetAddress[] {
InetAddresses.parseNumericAddress("198.50.100.10")
}));
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 IwlanTunnelMetricsImpl mMockIwlanTunnelMetrics;
@Mock private IkeSession mMockIkeSession;
@Mock private EpdgSelector mMockEpdgSelector;
@Mock private Network mMockNetwork;
@Mock CarrierConfigManager mMockCarrierConfigManager;
@Mock ConnectivityManager mMockConnectivityManager;
@Mock SubscriptionManager mMockSubscriptionManager;
@Mock SubscriptionInfo mMockSubscriptionInfo;
@Mock TelephonyManager mMockTelephonyManager;
@Mock IpSecManager mMockIpSecManager;
@Mock EpdgTunnelManager.IkeSessionCreator mMockIkeSessionCreator;
@Mock IkeException mMockIkeException;
@Mock IkeSessionConfiguration mMockIkeSessionConfiguration;
@Mock ChildSessionConfiguration mMockChildSessionConfiguration;
@Mock IpSecManager.IpSecTunnelInterface mMockIpSecTunnelInterface;
@Mock IkeSessionConnectionInfo mMockIkeSessionConnectionInfo;
@Mock IpSecTransform mMockedIpSecTransformIn;
@Mock IpSecTransform mMockedIpSecTransformOut;
@Mock LinkProperties mMockLinkProperties;
class IkeSessionArgumentCaptors {
ArgumentCaptor<IkeSessionParams> mIkeSessionParamsCaptor =
ArgumentCaptor.forClass(IkeSessionParams.class);
ArgumentCaptor<ChildSessionParams> mChildSessionParamsCaptor =
ArgumentCaptor.forClass(ChildSessionParams.class);
ArgumentCaptor<IkeSessionCallback> mIkeSessionCallbackCaptor =
ArgumentCaptor.forClass(IkeSessionCallback.class);
ArgumentCaptor<ChildSessionCallback> mChildSessionCallbackCaptor =
ArgumentCaptor.forClass(ChildSessionCallback.class);
}
@Before
public void setUp() throws Exception {
EpdgTunnelManager.resetAllInstances();
mEpdgTunnelManager = spy(EpdgTunnelManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX));
when(mMockContext.getSystemService(eq(IpSecManager.class))).thenReturn(mMockIpSecManager);
doReturn(mTestLooper.getLooper()).when(mEpdgTunnelManager).getLooper();
setVariable(mEpdgTunnelManager, "mContext", mMockContext);
mEpdgTunnelManager.initHandler();
mEpdgTunnelManager.resetTunnelManagerState();
doReturn(mMockEpdgSelector).when(mEpdgTunnelManager).getEpdgSelector();
when(mEpdgTunnelManager.getIkeSessionCreator()).thenReturn(mMockIkeSessionCreator);
when(mMockEpdgSelector.getValidatedServerList(
anyInt(),
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);
when(mMockIkeSessionConfiguration.getPcscfServers()).thenReturn(EXPECTED_PCSCF_ADDRESSES);
when(mMockChildSessionConfiguration.getInternalDnsServers())
.thenReturn(EXPECTED_DNS_ADDRESSES);
when(mMockChildSessionConfiguration.getInternalAddresses())
.thenReturn(EXPECTED_INTERNAL_ADDRESSES);
when(mMockIpSecManager.createIpSecTunnelInterface(any(), any(), any()))
.thenReturn(mMockIpSecTunnelInterface);
when(mMockIpSecTunnelInterface.getInterfaceName()).thenReturn("wlan0");
when(mMockIkeSessionConnectionInfo.getNetwork()).thenReturn(mMockNetwork);
doReturn(EXPECTED_LOCAL_ADDRESSES)
.when(mEpdgTunnelManager)
.getAddressForNetwork(any(), any());
}
@Test
public void testBringUpTunnelWithInvalidProtocol() {
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_PPP),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertFalse(ret);
}
@Test
public void testBringUpTunnelWithInvalidPduSessionId() {
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6, 16),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertFalse(ret);
ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6, -1),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
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, mMockIwlanTunnelMetrics);
assertTrue(ret);
ret =
mEpdgTunnelManager.bringUpTunnel(
TSR_v6, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
ret =
mEpdgTunnelManager.bringUpTunnel(
TSR_v4v6, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
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, mMockIwlanTunnelMetrics);
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, mMockIwlanTunnelMetrics);
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,
mMockIwlanTunnelMetrics,
null,
0);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
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, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
private void setupTunnelBringup(String apnName, int transactionId) 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(apnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(apnName, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), transactionId);
mTestLooper.dispatchAll();
}
private void setupTunnelBringup() throws Exception {
setupTunnelBringup(TEST_APN_NAME, 1 /* transactionId */);
}
@Test
@Ignore("b/239753287- Telus carrier errors out on parsing DEVICE_IDENTITY response")
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
@Ignore("b/239753287- Telus carrier errors out on parsing DEVICE_IDENTITY response")
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
@Ignore("b/239753287- Telus carrier errors out on parsing DEVICE_IDENTITY response")
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,
mMockIwlanTunnelMetrics);
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 testInitialContactForFirstTunnelOnly() throws Exception {
final String firstApnName = "ims";
final String secondApnName = "mms";
IkeSessionArgumentCaptors firstTunnelArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(firstApnName);
ChildSessionCallback firstCallback =
firstTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
IkeSessionArgumentCaptors secondTunnelArgumentCaptors =
verifyBringUpTunnel(secondApnName, true /* needPendingBringUpReq */);
verifyTunnelOnOpened(firstApnName, firstCallback);
ChildSessionCallback secondCallback =
secondTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
verifyTunnelOnOpened(secondApnName, secondCallback);
IkeSessionParams firstTunnelParams =
firstTunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue();
IkeSessionParams secondTunnelParams =
secondTunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue();
assertTrue(firstTunnelParams.hasIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT));
assertFalse(secondTunnelParams.hasIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT));
}
@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,
mMockIwlanTunnelMetrics,
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,
mMockIwlanTunnelMetrics,
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(),
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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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(),
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,
mMockIwlanTunnelMetrics);
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)
.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(),
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,
mMockIwlanTunnelMetrics);
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)
.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(),
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,
mMockIwlanTunnelMetrics);
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(),
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,
mMockIwlanTunnelMetrics);
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, 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(),
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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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(),
EXPECTED_EPDG_ADDRESSES.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,
});
if (!bundle.containsKey(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT)) {
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_PREFERRED);
}
when(mMockContext.getSystemService(eq(CarrierConfigManager.class)))
.thenReturn(mMockCarrierConfigManager);
when(mMockContext.getSystemService(eq(ConnectivityManager.class)))
.thenReturn(mMockConnectivityManager);
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 testHandleOnClosedWithEpdgConnected_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,
mMockIwlanTunnelMetrics,
null,
0);
int token = mEpdgTunnelManager.incrementAndGetCurrentTokenForApn(testApnName);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
mEpdgTunnelManager.setEpdgAddress(InetAddresses.parseNumericAddress(EPDG_ADDRESS));
mEpdgTunnelManager.getTmIkeSessionCallback(testApnName, token).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 testHandleOnClosedWithEpdgConnected_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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setHasConnectedToEpdg(false);
mEpdgTunnelManager.getTmIkeSessionCallback(testApnName, DEFAULT_TOKEN).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));
}
private void setOneTunnelOpened(String apnName) throws Exception {
mEpdgTunnelManager.putApnNameToTunnelConfig(
apnName,
mMockIkeSession,
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics,
null,
0);
setVariable(mEpdgTunnelManager, "mLocalAddresses", EXPECTED_LOCAL_ADDRESSES);
mEpdgTunnelManager.validateAndSetEpdgAddress(EXPECTED_EPDG_ADDRESSES);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
}
private IkeSessionArgumentCaptors verifyBringUpTunnelWithDnsQuery(String apnName) {
return verifyBringUpTunnelWithDnsQuery(apnName, null);
}
private IkeSessionArgumentCaptors verifyBringUpTunnelWithDnsQuery(
String apnName, IkeSession ikeSession) {
reset(mMockIwlanTunnelCallback);
IkeSessionArgumentCaptors ikeSessionArgumentCaptors = new IkeSessionArgumentCaptors();
verifyBringUpTunnel(apnName, true /* needPendingBringUpReq */);
doReturn(ikeSession)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionArgumentCaptors.mIkeSessionParamsCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionParamsCaptor.capture(),
any(Executor.class),
ikeSessionArgumentCaptors.mIkeSessionCallbackCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.capture());
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
verify(mMockIkeSessionCreator, times(1))
.createIkeSession(
eq(mMockContext),
ikeSessionArgumentCaptors.mIkeSessionParamsCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionParamsCaptor.capture(),
any(Executor.class),
ikeSessionArgumentCaptors.mIkeSessionCallbackCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.capture());
return ikeSessionArgumentCaptors;
}
private IkeSessionArgumentCaptors verifyBringUpTunnel(
String apnName, boolean needPendingBringUpReq) {
reset(mMockIkeSessionCreator);
IkeSessionArgumentCaptors ikeSessionArgumentCaptors = new IkeSessionArgumentCaptors();
doReturn(null)
.when(mMockIkeSessionCreator)
.createIkeSession(
eq(mMockContext),
ikeSessionArgumentCaptors.mIkeSessionParamsCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionParamsCaptor.capture(),
any(Executor.class),
ikeSessionArgumentCaptors.mIkeSessionCallbackCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.capture());
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(apnName));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(apnName, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockIkeSessionCreator, times(needPendingBringUpReq ? 0 : 1))
.createIkeSession(
eq(mMockContext),
ikeSessionArgumentCaptors.mIkeSessionParamsCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionParamsCaptor.capture(),
any(Executor.class),
ikeSessionArgumentCaptors.mIkeSessionCallbackCaptor.capture(),
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.capture());
return ikeSessionArgumentCaptors;
}
private void verifyTunnelOnOpened(String apnName, ChildSessionCallback childSessionCallback) {
doReturn(0L)
.when(mEpdgTunnelManager)
.reportIwlanError(eq(apnName), eq(new IwlanError(IwlanError.NO_ERROR)));
mEpdgTunnelManager
.getTmIkeSessionCallback(apnName, mEpdgTunnelManager.getCurrentTokenForApn(apnName))
.onOpened(mMockIkeSessionConfiguration);
mTestLooper.dispatchAll();
childSessionCallback.onIpSecTransformCreated(
mMockedIpSecTransformIn, IpSecManager.DIRECTION_IN);
mTestLooper.dispatchAll();
childSessionCallback.onIpSecTransformCreated(
mMockedIpSecTransformOut, IpSecManager.DIRECTION_OUT);
mTestLooper.dispatchAll();
childSessionCallback.onOpened(mMockChildSessionConfiguration);
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager, times(1))
.reportIwlanError(eq(apnName), eq(new IwlanError(IwlanError.NO_ERROR)));
verify(mMockIwlanTunnelCallback, times(1)).onOpened(eq(apnName), any());
}
@Test
public void testHandleOnOpenedWithEpdgConnected_True() throws Exception {
final String openedApnName = "ims";
final String toBeOpenedApnName = "mms";
setOneTunnelOpened(openedApnName);
IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
verifyBringUpTunnel(toBeOpenedApnName, false /* needPendingBringUpReq */);
ChildSessionCallback childSessionCallback =
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
verifyTunnelOnOpened(toBeOpenedApnName, childSessionCallback);
}
@Test
public void testServicePendingRequests() throws Exception {
final String firstApnName = "ims";
final String secondApnName = "mms";
IkeSessionArgumentCaptors firstTunnelArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(firstApnName);
ChildSessionCallback firstCallback =
firstTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
IkeSessionArgumentCaptors secondTunnelArgumentCaptors =
verifyBringUpTunnel(secondApnName, true /* needPendingBringUpReq */);
verifyTunnelOnOpened(firstApnName, firstCallback);
ChildSessionCallback secondCallback =
secondTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
verifyTunnelOnOpened(secondApnName, secondCallback);
}
@Test
public void testHandleOnClosedExceptionallyWithEpdgConnected_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,
mMockIwlanTunnelMetrics,
null,
0);
int token = mEpdgTunnelManager.incrementAndGetCurrentTokenForApn(testApnName);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
mEpdgTunnelManager.setEpdgAddress(InetAddresses.parseNumericAddress(EPDG_ADDRESS));
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, token)
.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 testHandleOnClosedExceptionallyWithEpdgConnected_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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setHasConnectedToEpdg(false);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, DEFAULT_TOKEN)
.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,
mMockIwlanTunnelMetrics,
null,
0);
int token = mEpdgTunnelManager.incrementAndGetCurrentTokenForApn(testApnName);
when(mMockIkeSessionConfiguration.getPcscfServers()).thenReturn(EXPECTED_EPDG_ADDRESSES);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, token)
.onOpened(mMockIkeSessionConfiguration);
mTestLooper.dispatchAll();
EpdgTunnelManager.TunnelConfig testApnTunnelConfig =
mEpdgTunnelManager.getTunnelConfigForApn(testApnName);
assertEquals(testApnTunnelConfig.getPcscfAddrList(), EXPECTED_EPDG_ADDRESSES);
}
@Test
public void testIkeSessionClosesWhenChildSessionTransformThrows() throws Exception {
String testApnName = "ims";
doThrow(new IllegalArgumentException())
.when(mMockIpSecManager)
.applyTunnelModeTransform(eq(mMockIpSecTunnelInterface), anyInt(), any());
IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(testApnName, mMockIkeSession);
ChildSessionCallback childSessionCallback =
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
childSessionCallback.onIpSecTransformCreated(
mMockedIpSecTransformIn, IpSecManager.DIRECTION_IN);
mTestLooper.dispatchAll();
verify(mMockIkeSession, times(1)).close();
}
@Test
public void testIkeSessionConnectionInfoChangedSetsUnderlyingNetwork() throws Exception {
String testApnName = "ims";
when(mMockConnectivityManager.getLinkProperties(any())).thenReturn(mMockLinkProperties);
IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(testApnName, mMockIkeSession);
ChildSessionCallback childSessionCallback =
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
childSessionCallback.onIpSecTransformCreated(
mMockedIpSecTransformIn, IpSecManager.DIRECTION_IN);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, DEFAULT_TOKEN)
.onIkeSessionConnectionInfoChanged(mMockIkeSessionConnectionInfo);
mTestLooper.dispatchAll();
verify(mMockIpSecTunnelInterface, times(1)).setUnderlyingNetwork(mMockNetwork);
}
@Test
public void testIkeSessionConnectionInfoChangedWithNullLinkPropertiesDoesNothing()
throws Exception {
String testApnName = "ims";
when(mMockConnectivityManager.getLinkProperties(any())).thenReturn(null);
IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(testApnName, mMockIkeSession);
ChildSessionCallback childSessionCallback =
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
childSessionCallback.onIpSecTransformCreated(
mMockedIpSecTransformIn, IpSecManager.DIRECTION_IN);
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, DEFAULT_TOKEN)
.onIkeSessionConnectionInfoChanged(mMockIkeSessionConnectionInfo);
mTestLooper.dispatchAll();
verify(mMockIpSecTunnelInterface, times(0)).setUnderlyingNetwork(any());
}
@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(),
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,
mMockIwlanTunnelMetrics);
} else {
ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, apnProtocol),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
}
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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,
mMockIwlanTunnelMetrics,
null,
0);
int token = mEpdgTunnelManager.incrementAndGetCurrentTokenForApn(testApnName);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
mEpdgTunnelManager.setEpdgAddress(InetAddresses.parseNumericAddress(EPDG_ADDRESS));
mEpdgTunnelManager
.getTmIkeSessionCallback(testApnName, token)
.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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(null, error, 1);
mTestLooper.dispatchAll();
mEpdgTunnelManager.setHasConnectedToEpdg(false);
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(testApnName), eq(error));
}
@Test
public void testNeverReportIwlanErrorWhenCloseAnOpenedTunnel() throws Exception {
IkeInternalException ikeException =
new IkeInternalException(new IOException("Retransmitting failure"));
IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
verifyBringUpTunnelWithDnsQuery(TEST_APN_NAME);
ChildSessionCallback childSessionCallback =
ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
verifyTunnelOnOpened(TEST_APN_NAME, childSessionCallback);
reset(mEpdgTunnelManager); // reset number of times of reportIwlanError()
mEpdgTunnelManager
.getTmIkeSessionCallback(TEST_APN_NAME, 0)
.onClosedExceptionally(ikeException);
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager, never()).reportIwlanError(eq(TEST_APN_NAME), any());
verify(mMockIwlanTunnelCallback, times(1))
.onClosed(eq(TEST_APN_NAME), eq(new IwlanError(ikeException)));
}
@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,
mMockIwlanTunnelMetrics);
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(),
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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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(),
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,
mMockIwlanTunnelMetrics);
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)
.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(),
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, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
// verify isRoaming, isEmergency and Network variables.
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
anyInt(), // only Ipv6 address is added
anyInt(),
eq(isRoaming),
eq(isEmergency),
eq(mMockNetwork),
any(EpdgSelector.EpdgSelectorCallback.class));
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, 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(mMockSubscriptionInfo)
.thenReturn(null);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
mEpdgTunnelManager.sendSelectionRequestComplete(
EXPECTED_EPDG_ADDRESSES, new IwlanError(IwlanError.NO_ERROR), 1);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(testApnName), eq(error));
}
@Test
public void testCloseTunnelWithEpdgSelectionIncomplete() throws Exception {
// Bring up tunnel
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP),
mMockIwlanTunnelCallback,
mMockIwlanTunnelMetrics);
assertTrue(ret);
// close tunnel when ePDG selection is incomplete
ret = mEpdgTunnelManager.closeTunnel(TEST_APN_NAME, false /*forceClose*/);
assertTrue(ret);
mTestLooper.dispatchAll();
ArgumentCaptor<OnClosedMetrics> metricsCaptor =
ArgumentCaptor.forClass(OnClosedMetrics.class);
verify(mMockIwlanTunnelMetrics, times(1)).onClosed(metricsCaptor.capture());
assertEquals(TEST_APN_NAME, metricsCaptor.getValue().getApnName());
assertNull(metricsCaptor.getValue().getEpdgServerAddress());
}
@Test
public void testIgnoreSignalFromObsoleteCallback() throws Exception {
int transactionId = 0;
// testApnName with token 0
setupTunnelBringup(TEST_APN_NAME, ++transactionId);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
IwlanError error = new IwlanError(mMockIkeException);
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(TEST_APN_NAME), eq(error));
mEpdgTunnelManager
.getTmIkeSessionCallback(TEST_APN_NAME, 0 /* token */)
.onClosedExceptionally(mMockIkeException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(TEST_APN_NAME), eq(error));
assertNull(mEpdgTunnelManager.getTunnelConfigForApn(TEST_APN_NAME));
// testApnName1 with token 1
setupTunnelBringup(TEST_APN_NAME, ++transactionId);
mEpdgTunnelManager.setHasConnectedToEpdg(true);
// signal from obsolete callback (token 0), ignore it
reset(mMockIwlanTunnelCallback);
mEpdgTunnelManager
.getTmIkeSessionCallback(TEST_APN_NAME, 0 /* token */)
.onClosedExceptionally(mMockIkeException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, never()).onClosed(eq(TEST_APN_NAME), eq(error));
assertNotNull(mEpdgTunnelManager.getTunnelConfigForApn(TEST_APN_NAME));
// signals from active callback
mEpdgTunnelManager
.getTmIkeSessionCallback(TEST_APN_NAME, 1 /* token */)
.onClosedExceptionally(mMockIkeException);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(TEST_APN_NAME), eq(error));
assertNull(mEpdgTunnelManager.getTunnelConfigForApn(TEST_APN_NAME));
}
@Test
public void testBringUpTunnelIpv4Preferred() throws Exception {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_PREFERRED);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
eq(EpdgSelector.IPV4_PREFERRED),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
@Test
public void testBringUpTunnelIpv6Preferred() throws Exception {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_PREFERRED);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
eq(EpdgSelector.IPV6_PREFERRED),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
@Test
public void testBringUpTunnelIpv4Only() throws Exception {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_ONLY);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4),
eq(EpdgSelector.SYSTEM_PREFERRED),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
@Test
public void testBringUpTunnelIpv6Only() throws Exception {
TunnelSetupRequest TSR =
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
doReturn(EXPECTED_IPV6_LOCAL_ADDRESSES)
.when(mEpdgTunnelManager)
.getAddressForNetwork(any(), any());
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV6),
eq(EpdgSelector.SYSTEM_PREFERRED),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
@Test
public void testBringUpTunnelIpv6OnlyOnIpv4Wifi() throws Exception {
TunnelSetupRequest TSR =
getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IPV6);
IwlanError error = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(TEST_APN_NAME), eq(error));
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector, never())
.getValidatedServerList(
anyInt(),
anyInt(),
anyInt(),
eq(false),
eq(false),
eq(mMockNetwork),
any());
verify(mEpdgTunnelManager, times(1)).reportIwlanError(eq(TEST_APN_NAME), eq(error));
verify(mMockIwlanTunnelCallback, times(1)).onClosed(eq(TEST_APN_NAME), eq(error));
}
@Test
public void testBringUpTunnelSystemPreferred() throws Exception {
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(
CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT,
CarrierConfigManager.Iwlan.EPDG_ADDRESS_SYSTEM_PREFERRED);
setupMockForGetConfig(bundle);
boolean ret =
mEpdgTunnelManager.bringUpTunnel(
TSR, mMockIwlanTunnelCallback, mMockIwlanTunnelMetrics);
assertTrue(ret);
mTestLooper.dispatchAll();
verify(mMockEpdgSelector)
.getValidatedServerList(
anyInt(),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
eq(EpdgSelector.SYSTEM_PREFERRED),
eq(false),
eq(false),
eq(mMockNetwork),
any());
}
}