blob: cc90ef4bd884096fe6a44fd5d6438bc4155a541e [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;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static org.junit.Assert.*;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.*;
import android.content.ContentResolver;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.test.TestLooper;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.DataFailCause;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
import android.telephony.data.IDataServiceCallback;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import com.google.android.iwlan.IwlanDataService.IwlanDataServiceProvider;
import com.google.android.iwlan.IwlanDataService.IwlanDataServiceProvider.IwlanTunnelCallback;
import com.google.android.iwlan.IwlanDataService.IwlanDataServiceProvider.TunnelState;
import com.google.android.iwlan.IwlanDataService.IwlanNetworkMonitorCallback;
import com.google.android.iwlan.epdg.EpdgSelector;
import com.google.android.iwlan.epdg.EpdgTunnelManager;
import com.google.android.iwlan.epdg.TunnelLinkProperties;
import com.google.android.iwlan.epdg.TunnelLinkPropertiesTest;
import com.google.android.iwlan.epdg.TunnelSetupRequest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class IwlanDataServiceTest {
private static final int DEFAULT_SLOT_INDEX = 0;
private static final int DEFAULT_SUB_INDEX = 0;
private static final int LINK_MTU = 1280;
private static final String TEST_APN_NAME = "ims";
private static final String IP_ADDRESS = "192.0.2.1";
private static final String DNS_ADDRESS = "8.8.8.8";
private static final String GATEWAY_ADDRESS = "0.0.0.0";
private static final String PSCF_ADDRESS = "10.159.204.230";
private static final String INTERFACE_NAME = "ipsec6";
@Mock private Context mMockContext;
@Mock private SubscriptionManager mMockSubscriptionManager;
@Mock private SubscriptionInfo mMockSubscriptionInfo;
@Mock private ContentResolver mMockContentResolver;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private DataServiceCallback mMockDataServiceCallback;
@Mock private EpdgTunnelManager mMockEpdgTunnelManager;
@Mock private IwlanDataServiceProvider mMockIwlanDataServiceProvider;
@Mock private Network mMockNetwork;
@Mock private TunnelLinkProperties mMockTunnelLinkProperties;
@Mock private ErrorPolicyManager mMockErrorPolicyManager;
@Mock private ImsManager mMockImsManager;
@Mock private ImsMmTelManager mMockImsMmTelManager;
@Mock private TelephonyManager mMockTelephonyManager;
@Mock private EpdgSelector mMockEpdgSelector;
@Mock private LinkProperties mMockLinkProperties;
@Mock private LinkAddress mMockIPv4LinkAddress;
@Mock private LinkAddress mMockIPv6LinkAddress;
@Mock private Inet4Address mMockInet4Address;
@Mock private Inet6Address mMockInet6Address;
MockitoSession mStaticMockSession;
private List<DataCallResponse> mResultDataCallList;
private @DataServiceCallback.ResultCode int mResultCode;
private CountDownLatch latch;
private IwlanDataService mIwlanDataService;
private IwlanDataServiceProvider mIwlanDataServiceProvider;
private IwlanDataServiceProvider mSpyIwlanDataServiceProvider;
private TestLooper mTestLooper = new TestLooper();
private final class IwlanDataServiceCallback extends IDataServiceCallback.Stub {
private final String mTag;
IwlanDataServiceCallback(String tag) {
mTag = tag;
}
@Override
public void onSetupDataCallComplete(
@DataServiceCallback.ResultCode int resultCode, DataCallResponse response) {}
@Override
public void onDeactivateDataCallComplete(@DataServiceCallback.ResultCode int resultCode) {}
@Override
public void onSetInitialAttachApnComplete(@DataServiceCallback.ResultCode int resultCode) {}
@Override
public void onSetDataProfileComplete(@DataServiceCallback.ResultCode int resultCode) {}
@Override
public void onRequestDataCallListComplete(
@DataServiceCallback.ResultCode int resultCode,
List<DataCallResponse> dataCallList) {
mResultCode = resultCode;
mResultDataCallList = new ArrayList<DataCallResponse>(dataCallList);
latch.countDown();
}
@Override
public void onDataCallListChanged(List<DataCallResponse> dataCallList) {}
@Override
public void onHandoverStarted(@DataServiceCallback.ResultCode int result) {}
@Override
public void onHandoverCancelled(@DataServiceCallback.ResultCode int result) {}
@Override
public void onApnUnthrottled(String apn) {}
@Override
public void onDataProfileUnthrottled(DataProfile dataProfile) {}
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mStaticMockSession =
mockitoSession()
.mockStatic(EpdgSelector.class)
.mockStatic(ErrorPolicyManager.class)
.mockStatic(IwlanBroadcastReceiver.class)
.mockStatic(IwlanHelper.class)
.strictness(Strictness.LENIENT)
.startMocking();
when(mMockContext.getSystemService(eq(ConnectivityManager.class)))
.thenReturn(mMockConnectivityManager);
when(mMockContext.getSystemService(eq(SubscriptionManager.class)))
.thenReturn(mMockSubscriptionManager);
when(mMockSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(anyInt()))
.thenReturn(mMockSubscriptionInfo);
when(mMockSubscriptionInfo.getSubscriptionId()).thenReturn(DEFAULT_SUB_INDEX);
when(mMockContext.getSystemService(eq(TelephonyManager.class)))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(eq(DEFAULT_SUB_INDEX)))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.isNetworkRoaming()).thenReturn(false);
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
when(mMockContext.getSystemService(eq(ImsManager.class))).thenReturn(mMockImsManager);
when(mMockImsManager.getImsMmTelManager(anyInt())).thenReturn(mMockImsMmTelManager);
when(mMockImsMmTelManager.isVoWiFiSettingEnabled()).thenReturn(false);
when(EpdgSelector.getSelectorInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(mMockEpdgSelector);
when(mMockIPv4LinkAddress.getAddress()).thenReturn(mMockInet4Address);
when(mMockIPv6LinkAddress.getAddress()).thenReturn(mMockInet6Address);
mIwlanDataService = spy(new IwlanDataService());
doReturn(mTestLooper.getLooper()).when(mIwlanDataService).getLooper();
mIwlanDataService.setAppContext(mMockContext);
mIwlanDataServiceProvider =
(IwlanDataServiceProvider)
mIwlanDataService.onCreateDataServiceProvider(DEFAULT_SLOT_INDEX);
mTestLooper.dispatchAll();
mSpyIwlanDataServiceProvider = spy(mIwlanDataServiceProvider);
}
@After
public void cleanUp() throws Exception {
mStaticMockSession.finishMocking();
mIwlanDataServiceProvider.close();
mTestLooper.dispatchAll();
if (mIwlanDataService != null) {
mIwlanDataService.onDestroy();
}
}
private void verifiyNetworkConnected(int transportType) {
NetworkCapabilities mockNetworkCapabilities = mock(NetworkCapabilities.class);
when(mockNetworkCapabilities.hasTransport(anyInt())).thenReturn(false);
when(mockNetworkCapabilities.hasTransport(eq(transportType))).thenReturn(true);
IwlanNetworkMonitorCallback networkMonitorCallback =
mIwlanDataService.getNetworkMonitorCallback();
networkMonitorCallback.onCapabilitiesChanged(mMockNetwork, mockNetworkCapabilities);
}
private void verifiyNetworkLost(int transportType) {
IwlanNetworkMonitorCallback networkMonitorCallback =
mIwlanDataService.getNetworkMonitorCallback();
networkMonitorCallback.onLost(mMockNetwork);
}
@Test
public void testWifionConnected() {
verifiyNetworkConnected(TRANSPORT_WIFI);
assertTrue(mIwlanDataService.isNetworkConnected(false, false));
}
@Test
public void testWifiOnLost() {
when(mMockIwlanDataServiceProvider.getSlotIndex()).thenReturn(DEFAULT_SLOT_INDEX + 1);
mIwlanDataService.addIwlanDataServiceProvider(mMockIwlanDataServiceProvider);
verifiyNetworkLost(TRANSPORT_WIFI);
assertFalse(mIwlanDataService.isNetworkConnected(false, false));
verify(mMockIwlanDataServiceProvider).forceCloseTunnelsInDeactivatingState();
mIwlanDataService.removeDataServiceProvider(mMockIwlanDataServiceProvider);
mTestLooper.dispatchAll();
}
@Test
public void testAddDuplicateDataServiceProviderThrows() throws Exception {
when(mMockIwlanDataServiceProvider.getSlotIndex()).thenReturn(DEFAULT_SLOT_INDEX);
assertThrows(
IllegalStateException.class,
() -> mIwlanDataService.addIwlanDataServiceProvider(mMockIwlanDataServiceProvider));
}
@Test
public void testRemoveDataServiceProvider() {
when(mMockIwlanDataServiceProvider.getSlotIndex()).thenReturn(DEFAULT_SLOT_INDEX);
mIwlanDataService.removeDataServiceProvider(mMockIwlanDataServiceProvider);
mTestLooper.dispatchAll();
verify(mIwlanDataService, times(1)).deinitNetworkCallback();
assertEquals(mIwlanDataService.mIwlanDataServiceHandler, null);
mIwlanDataService.onCreateDataServiceProvider(DEFAULT_SLOT_INDEX);
mTestLooper.dispatchAll();
}
@Test
public void testRequestDataCallListPass() throws Exception {
DataProfile dp = buildDataProfile();
List<LinkAddress> mInternalAddressList;
List<InetAddress> mDNSAddressList;
List<InetAddress> mGatewayAddressList;
List<InetAddress> mPCSFAddressList;
latch = new CountDownLatch(1);
IwlanDataServiceCallback callback = new IwlanDataServiceCallback("requestDataCallList");
TunnelLinkProperties mLinkProperties =
TunnelLinkPropertiesTest.createTestTunnelLinkProperties();
mIwlanDataServiceProvider.setTunnelState(
dp,
new DataServiceCallback(callback),
TunnelState.TUNNEL_UP,
mLinkProperties,
false,
1);
mIwlanDataServiceProvider.requestDataCallList(new DataServiceCallback(callback));
mTestLooper.dispatchAll();
latch.await(1, TimeUnit.SECONDS);
assertEquals(mResultCode, DataServiceCallback.RESULT_SUCCESS);
assertEquals(mResultDataCallList.size(), 1);
for (DataCallResponse dataCallInfo : mResultDataCallList) {
assertEquals(dataCallInfo.getId(), TEST_APN_NAME.hashCode());
assertEquals(dataCallInfo.getLinkStatus(), DataCallResponse.LINK_STATUS_ACTIVE);
assertEquals(dataCallInfo.getProtocolType(), ApnSetting.PROTOCOL_IPV4V6);
assertEquals(dataCallInfo.getInterfaceName(), INTERFACE_NAME);
mInternalAddressList = dataCallInfo.getAddresses();
assertEquals(mInternalAddressList.size(), 1);
for (LinkAddress mLinkAddress : mInternalAddressList) {
assertEquals(mLinkAddress, new LinkAddress(InetAddress.getByName(IP_ADDRESS), 3));
}
mDNSAddressList = dataCallInfo.getDnsAddresses();
assertEquals(mDNSAddressList.size(), 1);
for (InetAddress mInetAddress : mDNSAddressList) {
assertEquals(mInetAddress, InetAddress.getByName(DNS_ADDRESS));
}
mGatewayAddressList = dataCallInfo.getGatewayAddresses();
assertEquals(mGatewayAddressList.size(), 1);
for (InetAddress mInetAddress : mGatewayAddressList) {
assertEquals(mInetAddress, Inet4Address.getByName(GATEWAY_ADDRESS));
}
mPCSFAddressList = dataCallInfo.getPcscfAddresses();
assertEquals(mPCSFAddressList.size(), 1);
for (InetAddress mInetAddress : mPCSFAddressList) {
assertEquals(mInetAddress, InetAddress.getByName(PSCF_ADDRESS));
}
assertEquals(dataCallInfo.getMtuV4(), LINK_MTU);
assertEquals(dataCallInfo.getMtuV6(), LINK_MTU);
}
}
@Test
public void testRequestDataCallListEmpty() throws Exception {
latch = new CountDownLatch(1);
IwlanDataServiceCallback callback = new IwlanDataServiceCallback("requestDataCallList");
mIwlanDataServiceProvider.requestDataCallList(new DataServiceCallback(callback));
mTestLooper.dispatchAll();
latch.await(1, TimeUnit.SECONDS);
assertEquals(mResultCode, DataServiceCallback.RESULT_SUCCESS);
assertEquals(mResultDataCallList.size(), 0);
}
@Test
public void testIwlanSetupDataCallWithInvalidArg() {
mIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.UNKNOWN, /* AccessNetworkType */
null, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
2, /* pdu session id */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, timeout(1000).times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_ERROR_INVALID_ARG), isNull());
}
@Test
public void testIwlanSetupDataCallWithIllegalState() {
DataProfile dp = buildDataProfile();
/* Wifi is not connected */
mIwlanDataService.setNetworkConnected(
false, mMockNetwork, IwlanDataService.Transport.UNSPECIFIED_NETWORK);
mIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pdu session id */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, timeout(1000).times(1))
.onSetupDataCallComplete(
eq(5 /*DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE */),
isNull());
}
@Test
public void testIwlanDeactivateDataCallWithInvalidArg() {
mIwlanDataServiceProvider.deactivateDataCall(
0, /* cid */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, timeout(1000).times(1))
.onDeactivateDataCallComplete(eq(DataServiceCallback.RESULT_ERROR_INVALID_ARG));
}
@Test
public void testIwlanSetupDataCallWithBringUpTunnel() {
DataProfile dp = buildDataProfile();
/* Wifi is connected */
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
/* Check bringUpTunnel() is called. */
verify(mMockEpdgTunnelManager, times(1))
.bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
/* Check callback result is RESULT_SUCCESS when onOpened() is called. */
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onOpened(TEST_APN_NAME, mMockTunnelLinkProperties);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), any(DataCallResponse.class));
}
@Test
public void testSliceInfoInclusionInDataCallResponse() throws Exception {
DataProfile dp = buildDataProfile();
/* Wifi is connected */
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
/* Check bringUpTunnel() is called. */
verify(mMockEpdgTunnelManager, times(1))
.bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
/* Check callback result is RESULT_SUCCESS when onOpened() is called. */
TunnelLinkProperties tp = TunnelLinkPropertiesTest.createTestTunnelLinkProperties();
ArgumentCaptor<DataCallResponse> dataCallResponseCaptor =
ArgumentCaptor.forClass(DataCallResponse.class);
mSpyIwlanDataServiceProvider.getIwlanTunnelCallback().onOpened(TEST_APN_NAME, tp);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), dataCallResponseCaptor.capture());
/* check that sliceinfo is filled up and matches */
DataCallResponse dataCallResponse = dataCallResponseCaptor.getValue();
assertNotNull(dataCallResponse.getSliceInfo());
assertEquals(dataCallResponse.getSliceInfo(), tp.sliceInfo().get());
}
@Test
public void testIwlanDeactivateDataCallWithCloseTunnel() {
DataProfile dp = buildDataProfile();
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
verifiyNetworkConnected(TRANSPORT_WIFI);
mSpyIwlanDataServiceProvider.setTunnelState(
dp, mMockDataServiceCallback, TunnelState.TUNNEL_IN_BRINGUP, null, false, 1);
mSpyIwlanDataServiceProvider.deactivateDataCall(
TEST_APN_NAME.hashCode() /* cid: hashcode() of "ims" */,
DataService.REQUEST_REASON_NORMAL,
mMockDataServiceCallback);
mTestLooper.dispatchAll();
/* Check closeTunnel() is called. */
verify(mMockEpdgTunnelManager, times(1)).closeTunnel(eq(TEST_APN_NAME), eq(false));
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.NO_ERROR));
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, times(1))
.onDeactivateDataCallComplete(eq(DataServiceCallback.RESULT_SUCCESS));
}
@Test
public void testIwlanDeactivateDataCallAfterSuccessHandover() {
DataProfile dp = buildDataProfile();
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
verifiyNetworkConnected(TRANSPORT_WIFI);
mSpyIwlanDataServiceProvider.setTunnelState(
dp, mMockDataServiceCallback, TunnelState.TUNNEL_IN_BRINGUP, null, false, 1);
mSpyIwlanDataServiceProvider.deactivateDataCall(
TEST_APN_NAME.hashCode() /* cid: hashcode() of "ims" */,
DataService.REQUEST_REASON_HANDOVER,
mMockDataServiceCallback);
mTestLooper.dispatchAll();
/* Check closeTunnel() is called. */
verify(mMockEpdgTunnelManager, times(1)).closeTunnel(eq(TEST_APN_NAME), eq(true));
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.NO_ERROR));
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, times(1))
.onDeactivateDataCallComplete(eq(DataServiceCallback.RESULT_SUCCESS));
}
@Test
public void testHandoverFailureModeNormal() {
DataProfile dp = buildDataProfile();
int setupDataReason = DataService.REQUEST_REASON_NORMAL;
when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(mMockErrorPolicyManager);
when(mMockErrorPolicyManager.getCurrentRetryTimeMs(eq(TEST_APN_NAME))).thenReturn(5L);
when(mMockErrorPolicyManager.getDataFailCause(eq(TEST_APN_NAME)))
.thenReturn(DataFailCause.USER_AUTHENTICATION);
mSpyIwlanDataServiceProvider.setTunnelState(
dp,
mMockDataServiceCallback,
TunnelState.TUNNEL_IN_BRINGUP,
null,
(setupDataReason == DataService.REQUEST_REASON_HANDOVER),
1);
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.NO_ERROR));
mTestLooper.dispatchAll();
ArgumentCaptor<DataCallResponse> dataCallResponseCaptor =
ArgumentCaptor.forClass(DataCallResponse.class);
verify(mMockDataServiceCallback, times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), dataCallResponseCaptor.capture());
DataCallResponse dataCallResponse = dataCallResponseCaptor.getValue();
assertEquals(
dataCallResponse.getHandoverFailureMode(),
DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
assertEquals(dataCallResponse.getCause(), DataFailCause.USER_AUTHENTICATION);
assertEquals(dataCallResponse.getRetryDurationMillis(), 5L);
}
@Test
public void testHandoverFailureModeHandover() {
DataProfile dp = buildDataProfile();
int setupDataReason = DataService.REQUEST_REASON_HANDOVER;
when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(mMockErrorPolicyManager);
when(mMockErrorPolicyManager.getCurrentRetryTimeMs(eq(TEST_APN_NAME))).thenReturn(-1L);
when(mMockErrorPolicyManager.getDataFailCause(eq(TEST_APN_NAME)))
.thenReturn(DataFailCause.ERROR_UNSPECIFIED);
mSpyIwlanDataServiceProvider.setTunnelState(
dp,
mMockDataServiceCallback,
TunnelState.TUNNEL_IN_BRINGUP,
null,
(setupDataReason == DataService.REQUEST_REASON_HANDOVER),
1);
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.NO_ERROR));
mTestLooper.dispatchAll();
ArgumentCaptor<DataCallResponse> dataCallResponseCaptor =
ArgumentCaptor.forClass(DataCallResponse.class);
verify(mMockDataServiceCallback, times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), dataCallResponseCaptor.capture());
DataCallResponse dataCallResponse = dataCallResponseCaptor.getValue();
assertEquals(
dataCallResponse.getHandoverFailureMode(),
DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
assertEquals(dataCallResponse.getCause(), DataFailCause.ERROR_UNSPECIFIED);
assertEquals(dataCallResponse.getRetryDurationMillis(), -1L);
}
@Test
public void testDnsPrefetching() throws Exception {
IwlanNetworkMonitorCallback mNetworkMonitorCallback =
mIwlanDataService.getNetworkMonitorCallback();
/* Wifi is connected */
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
List<LinkAddress> linkAddresses = new ArrayList<>();
linkAddresses.add(mMockIPv4LinkAddress);
when(mMockLinkProperties.getLinkAddresses()).thenReturn(linkAddresses);
mNetworkMonitorCallback.onLinkPropertiesChanged(mMockNetwork, mMockLinkProperties);
mIwlanDataService
.mIwlanDataServiceHandler
.obtainMessage(
IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT,
DEFAULT_SLOT_INDEX,
0 /* unused */)
.sendToTarget();
mIwlanDataService
.mIwlanDataServiceHandler
.obtainMessage(
IwlanEventListener.WIFI_CALLING_ENABLE_EVENT,
DEFAULT_SLOT_INDEX,
0 /* unused */)
.sendToTarget();
mTestLooper.dispatchAll();
linkAddresses.add(mMockIPv6LinkAddress);
when(mMockLinkProperties.getLinkAddresses()).thenReturn(linkAddresses);
mNetworkMonitorCallback.onLinkPropertiesChanged(mMockNetwork, mMockLinkProperties);
/* Prefetching will be triggered twice.
1. Network connected, CarrierConfig ready, WifiCallingSetting enabled
2. Connection ipFamily changed.
*/
verify(mMockEpdgSelector, times(2))
.getValidatedServerList(
eq(0),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
eq(false),
eq(false),
eq(mMockNetwork),
isNull());
verify(mMockEpdgSelector, times(2))
.getValidatedServerList(
eq(0),
eq(EpdgSelector.PROTO_FILTER_IPV4V6),
eq(false),
eq(true),
eq(mMockNetwork),
isNull());
}
private void sleep(long time) {
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
private DataProfile buildDataProfile() {
DataProfile dp =
new DataProfile.Builder()
.setProfileId(1)
.setApn(TEST_APN_NAME)
.setProtocolType(ApnSetting.PROTOCOL_IPV4V6) // IPv4v6
.setAuthType(0) // none
.setUserName("")
.setPassword("")
.setType(1) // 3gpp
// .setMaxConnectionsTime(1)
// .setMaxConnections(3)
// .setWaitTime(10)
.enable(true)
.setSupportedApnTypesBitmask(ApnSetting.TYPE_IMS)
.setRoamingProtocolType(ApnSetting.PROTOCOL_IPV4V6) // IPv4v6
.setBearerBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN)
.setPersistent(true)
.setPreferred(true)
.build();
return dp;
}
@Test
public void testIwlanSetupDataCallWithCellularAndCstDisabled() {
DataProfile dp = buildDataProfile();
/* Mobile is connected */
mIwlanDataService.setNetworkConnected(
true, mMockNetwork, IwlanDataService.Transport.MOBILE);
lenient()
.when(
IwlanHelper.isCrossSimCallingEnabled(
eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(false);
lenient()
.when(IwlanHelper.isDefaultDataSlot(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(true);
mIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pdu session id */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, timeout(1000).times(1))
.onSetupDataCallComplete(
eq(5 /* DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE */),
isNull());
}
@Test
public void testIwlanSetupDataCallWithCellularAndCstEnabled() {
DataProfile dp = buildDataProfile();
/* Clear state */
mIwlanDataService.setNetworkConnected(
false, mMockNetwork, IwlanDataService.Transport.UNSPECIFIED_NETWORK);
/* Mobile is connected */
mIwlanDataService.setNetworkConnected(
true, mMockNetwork, IwlanDataService.Transport.MOBILE);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
lenient()
.when(
IwlanHelper.isCrossSimCallingEnabled(
eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(true);
lenient()
.when(IwlanHelper.isDefaultDataSlot(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(false);
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
mTestLooper.dispatchAll();
/* Check bringUpTunnel() is called. */
verify(mMockEpdgTunnelManager, times(1))
.bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
/* Check callback result is RESULT_SUCCESS when onOpened() is called. */
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onOpened(TEST_APN_NAME, mMockTunnelLinkProperties);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, times(1))
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), any(DataCallResponse.class));
}
@Test
public void testIwlanTunnelStatsFailureCounts() {
DataProfile dp = buildDataProfile();
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(mMockErrorPolicyManager);
long count = 3L;
for (int i = 0; i < count; i++) {
mockTunnelSetupFail(dp);
sleep(1000);
}
IwlanDataServiceProvider.IwlanDataTunnelStats stats =
mSpyIwlanDataServiceProvider.getTunnelStats();
long result = stats.mTunnelSetupFailureCounts.get(TEST_APN_NAME);
assertEquals(result, count);
}
@Test
public void testIwlanTunnelStatsUnsolDownCounts() {
DataProfile dp = buildDataProfile();
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
long count = 3L;
for (int i = 0; i < count; i++) {
mockTunnelSetupSuccess(dp, 0);
mockUnsolTunnelDown();
}
IwlanDataServiceProvider.IwlanDataTunnelStats stats =
mSpyIwlanDataServiceProvider.getTunnelStats();
long result = stats.mUnsolTunnelDownCounts.get(TEST_APN_NAME);
assertEquals(result, count);
}
@Test
public void testIwlanTunnelStats() {
DataProfile dp = buildDataProfile();
mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
LongSummaryStatistics tunnelSetupSuccessStats = new LongSummaryStatistics();
LongSummaryStatistics tunnelUpStats = new LongSummaryStatistics();
Date beforeSetup = Calendar.getInstance().getTime();
mockTunnelSetupSuccess(dp, 0);
Date tunnelUp = Calendar.getInstance().getTime();
mockDeactivateTunnelDown(0);
Date tunnelDown = Calendar.getInstance().getTime();
tunnelSetupSuccessStats.accept(tunnelUp.getTime() - beforeSetup.getTime());
tunnelUpStats.accept(tunnelDown.getTime() - tunnelUp.getTime());
beforeSetup = Calendar.getInstance().getTime();
mockTunnelSetupSuccess(dp, 1000);
tunnelUp = Calendar.getInstance().getTime();
mockDeactivateTunnelDown(3000);
tunnelDown = Calendar.getInstance().getTime();
tunnelSetupSuccessStats.accept(tunnelUp.getTime() - beforeSetup.getTime());
tunnelUpStats.accept(tunnelDown.getTime() - tunnelUp.getTime());
beforeSetup = Calendar.getInstance().getTime();
mockTunnelSetupSuccess(dp, 600);
tunnelUp = Calendar.getInstance().getTime();
mockDeactivateTunnelDown(500);
tunnelDown = Calendar.getInstance().getTime();
tunnelSetupSuccessStats.accept(tunnelUp.getTime() - beforeSetup.getTime());
tunnelUpStats.accept(tunnelDown.getTime() - tunnelUp.getTime());
IwlanDataServiceProvider.IwlanDataTunnelStats stats =
mSpyIwlanDataServiceProvider.getTunnelStats();
LongSummaryStatistics finalSetupStats = stats.mTunnelSetupSuccessStats.get(TEST_APN_NAME);
LongSummaryStatistics finalUpStats = stats.mTunnelUpStats.get(TEST_APN_NAME);
assertEquals(finalSetupStats.getAverage(), tunnelSetupSuccessStats.getAverage(), 100);
assertEquals(finalSetupStats.getCount(), tunnelSetupSuccessStats.getCount());
assertEquals(finalSetupStats.getMax(), tunnelSetupSuccessStats.getMax(), 100);
assertEquals(finalUpStats.getAverage(), tunnelUpStats.getAverage(), 100);
assertEquals(finalUpStats.getCount(), tunnelUpStats.getCount());
assertEquals(finalUpStats.getMax(), tunnelUpStats.getMax(), 100);
}
private void mockTunnelSetupFail(DataProfile dp) {
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
doReturn(true)
.when(mMockEpdgTunnelManager)
.bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.IKE_INTERNAL_IO_EXCEPTION));
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, atLeastOnce())
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), any(DataCallResponse.class));
}
private void mockTunnelSetupSuccess(DataProfile dp, long sleepTime) {
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
dp, /* dataProfile */
false, /* isRoaming */
true, /* allowRoaming */
DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
null, /* trafficDescriptor */
true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
doReturn(true)
.when(mMockEpdgTunnelManager)
.bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
mTestLooper.dispatchAll();
sleep(sleepTime);
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onOpened(TEST_APN_NAME, mMockTunnelLinkProperties);
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, atLeastOnce())
.onSetupDataCallComplete(
eq(DataServiceCallback.RESULT_SUCCESS), any(DataCallResponse.class));
}
private void mockUnsolTunnelDown() {
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.IKE_INTERNAL_IO_EXCEPTION));
mTestLooper.dispatchAll();
}
private void mockDeactivateTunnelDown(long sleepTime) {
mSpyIwlanDataServiceProvider.deactivateDataCall(
TEST_APN_NAME.hashCode() /* cid: hashcode() of "ims" */,
DataService.REQUEST_REASON_NORMAL /* DataService.REQUEST_REASON_NORMAL */,
mMockDataServiceCallback);
mTestLooper.dispatchAll();
verify(mMockEpdgTunnelManager, atLeastOnce()).closeTunnel(eq(TEST_APN_NAME), anyBoolean());
sleep(sleepTime);
mSpyIwlanDataServiceProvider
.getIwlanTunnelCallback()
.onClosed(TEST_APN_NAME, new IwlanError(IwlanError.NO_ERROR));
mTestLooper.dispatchAll();
verify(mMockDataServiceCallback, atLeastOnce())
.onDeactivateDataCallComplete(eq(DataServiceCallback.RESULT_SUCCESS));
}
}