| /* |
| * Copyright 2021 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.android.internal.telephony.data; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyBoolean; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.ArgumentMatchers.nullable; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| |
| import android.net.InetAddresses; |
| import android.net.LinkAddress; |
| import android.net.LinkProperties; |
| import android.net.NetworkCapabilities; |
| import android.net.NetworkRequest; |
| import android.os.AsyncResult; |
| import android.os.Looper; |
| import android.os.Message; |
| import android.telephony.AccessNetworkConstants; |
| import android.telephony.AccessNetworkConstants.AccessNetworkType; |
| import android.telephony.AccessNetworkConstants.TransportType; |
| import android.telephony.Annotation.DataFailureCause; |
| import android.telephony.DataFailCause; |
| import android.telephony.NetworkRegistrationInfo; |
| import android.telephony.PreciseDataConnectionState; |
| import android.telephony.ServiceState; |
| 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.NetworkSliceInfo; |
| import android.telephony.data.TrafficDescriptor; |
| import android.testing.AndroidTestingRunner; |
| import android.testing.TestableLooper; |
| import android.util.Pair; |
| import android.util.SparseArray; |
| |
| import com.android.internal.telephony.TelephonyTest; |
| import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason; |
| import com.android.internal.telephony.data.DataNetwork.DataNetworkCallback; |
| import com.android.internal.telephony.metrics.DataCallSessionStats; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Mockito; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| |
| @RunWith(AndroidTestingRunner.class) |
| @TestableLooper.RunWithLooper |
| public class DataNetworkTest extends TelephonyTest { |
| private static final String IPV4_ADDRESS = "10.0.2.15"; |
| private static final String IPV6_ADDRESS = "2607:fb90:a620:651d:eabe:f8da:c107:44be"; |
| |
| private static final int ADMIN_UID1 = 1234; |
| private static final int ADMIN_UID2 = 5678; |
| |
| private DataNetwork mDataNetworkUT; |
| |
| private final SparseArray<DataServiceManager> mDataServiceManagers = new SparseArray<>(); |
| |
| private final ApnSetting mInternetApnSetting = new ApnSetting.Builder() |
| .setId(2163) |
| .setOperatorNumeric("12345") |
| .setEntryName("fake_apn") |
| .setApnName("fake_apn") |
| .setUser("user") |
| .setPassword("passwd") |
| .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL) |
| .setProtocol(ApnSetting.PROTOCOL_IPV6) |
| .setRoamingProtocol(ApnSetting.PROTOCOL_IP) |
| .setCarrierEnabled(true) |
| .setNetworkTypeBitmask(0) |
| .setProfileId(1234) |
| .setMaxConns(321) |
| .setWaitTime(456) |
| .setMaxConnsTime(789) |
| .build(); |
| |
| private final ApnSetting mImsApnSetting = new ApnSetting.Builder() |
| .setId(2163) |
| .setOperatorNumeric("12345") |
| .setEntryName("fake_ims") |
| .setApnName("fake_ims") |
| .setUser("user") |
| .setPassword("passwd") |
| .setApnTypeBitmask(ApnSetting.TYPE_IMS) |
| .setProtocol(ApnSetting.PROTOCOL_IPV6) |
| .setRoamingProtocol(ApnSetting.PROTOCOL_IP) |
| .setCarrierEnabled(true) |
| .setNetworkTypeBitmask(0) |
| .setProfileId(1234) |
| .setMaxConns(321) |
| .setWaitTime(456) |
| .setMaxConnsTime(789) |
| .build(); |
| |
| private final DataProfile mInternetDataProfile = new DataProfile.Builder() |
| .setApnSetting(mInternetApnSetting) |
| .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) |
| .build(); |
| |
| private final DataProfile mImsDataProfile = new DataProfile.Builder() |
| .setApnSetting(mImsApnSetting) |
| .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) |
| .build(); |
| |
| private final DataProfile mEnterpriseDataProfile = new DataProfile.Builder() |
| .setTrafficDescriptor(new TrafficDescriptor(null, |
| new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID, |
| "ENTERPRISE", 1).getBytes())) |
| .build(); |
| |
| private final DataProfile mUrlccDataProfile = new DataProfile.Builder() |
| .setTrafficDescriptor(new TrafficDescriptor(null, |
| new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID, |
| "PRIORITIZE_LATENCY", 1).getBytes())) |
| .build(); |
| |
| private final DataProfile mEmbbDataProfile = new DataProfile.Builder() |
| .setTrafficDescriptor(new TrafficDescriptor(null, |
| new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID, |
| "PRIORITIZE_BANDWIDTH", 1).getBytes())) |
| .build(); |
| |
| // Mocked classes |
| private DataNetworkCallback mDataNetworkCallback; |
| private DataCallSessionStats mDataCallSessionStats; |
| |
| private final NetworkRegistrationInfo mIwlanNetworkRegistrationInfo = |
| new NetworkRegistrationInfo.Builder() |
| .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN) |
| .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) |
| .build(); |
| |
| private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid) { |
| setSuccessfulSetupDataResponse(dsm, cid, Collections.emptyList()); |
| } |
| |
| private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid, |
| List<TrafficDescriptor> tds) { |
| doAnswer(invocation -> { |
| final Message msg = (Message) invocation.getArguments()[10]; |
| |
| DataCallResponse response = new DataCallResponse.Builder() |
| .setCause(0) |
| .setRetryDurationMillis(-1L) |
| .setId(cid) |
| .setLinkStatus(2) |
| .setProtocolType(ApnSetting.PROTOCOL_IPV4V6) |
| .setInterfaceName("ifname") |
| .setAddresses(Arrays.asList( |
| new LinkAddress(InetAddresses.parseNumericAddress(IPV4_ADDRESS), 32), |
| new LinkAddress(IPV6_ADDRESS + "/64"))) |
| .setDnsAddresses(Arrays.asList(InetAddresses.parseNumericAddress("10.0.2.3"), |
| InetAddresses.parseNumericAddress("fd00:976a::9"))) |
| .setGatewayAddresses(Arrays.asList( |
| InetAddresses.parseNumericAddress("10.0.2.15"), |
| InetAddresses.parseNumericAddress("fe80::2"))) |
| .setPcscfAddresses(Arrays.asList( |
| InetAddresses.parseNumericAddress("fd00:976a:c305:1d::8"), |
| InetAddresses.parseNumericAddress("fd00:976a:c202:1d::7"), |
| InetAddresses.parseNumericAddress("fd00:976a:c305:1d::5"))) |
| .setMtu(1500) |
| .setMtuV4(1500) |
| .setMtuV6(1500) |
| .setPduSessionId(1) |
| .setQosBearerSessions(new ArrayList<>()) |
| .setTrafficDescriptors(tds) |
| .build(); |
| msg.getData().putParcelable("data_call_response", response); |
| msg.arg1 = DataServiceCallback.RESULT_SUCCESS; |
| msg.sendToTarget(); |
| return null; |
| }).when(dsm).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), |
| anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), |
| any(Message.class)); |
| } |
| |
| private void setFailedSetupDataResponse(DataServiceManager dsm, |
| @DataServiceCallback.ResultCode int resultCode) { |
| doAnswer(invocation -> { |
| final Message msg = (Message) invocation.getArguments()[10]; |
| msg.arg1 = resultCode; |
| msg.sendToTarget(); |
| return null; |
| }).when(dsm).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), |
| anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), |
| any(Message.class)); |
| } |
| |
| private void sendServiceStateChangedEvent(@ServiceState.RegState int dataRegState, |
| @ServiceState.RilRadioTechnology int rat) { |
| mDataNetworkUT.obtainMessage(9/*EVENT_SERVICE_STATE_CHANGED*/, |
| new AsyncResult(null, new Pair<>(dataRegState, rat), null)).sendToTarget(); |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| super.setUp(getClass().getSimpleName()); |
| mDataNetworkCallback = Mockito.mock(DataNetworkCallback.class); |
| mDataCallSessionStats = Mockito.mock(DataCallSessionStats.class); |
| doReturn(true).when(mPhone).isUsingNewDataStack(); |
| doAnswer(invocation -> { |
| ((Runnable) invocation.getArguments()[0]).run(); |
| return null; |
| }).when(mDataNetworkCallback).invokeFromExecutor(any(Runnable.class)); |
| mDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, |
| mMockedWwanDataServiceManager); |
| mDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, |
| mMockedWlanDataServiceManager); |
| doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed(); |
| doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager) |
| .getPreferredTransportByNetworkCapability(anyInt()); |
| doReturn(DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR) |
| .when(mDataConfigManager).getBandwidthEstimateSource(); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| mDataNetworkUT = null; |
| mDataServiceManagers.clear(); |
| super.tearDown(); |
| } |
| |
| private void sendTearDownEvent(@TransportType int transport, int cid, |
| @DataFailureCause int cause) { |
| DataCallResponse response = new DataCallResponse.Builder() |
| .setCause(cause) |
| .setRetryDurationMillis(DataCallResponse.RETRY_DURATION_UNDEFINED) |
| .setId(cid) |
| .setLinkStatus(DataCallResponse.LINK_STATUS_INACTIVE) |
| .setProtocolType(ApnSetting.PROTOCOL_IPV4V6) |
| .setQosBearerSessions(new ArrayList<>()) |
| .setTrafficDescriptors(new ArrayList<>()) |
| .build(); |
| mDataNetworkUT.sendMessage(7/*EVENT_TEAR_DOWN_NETWORK*/, |
| 1/*TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED*/); |
| mDataNetworkUT.sendMessage(8/*EVENT_DATA_STATE_CHANGED*/, |
| new AsyncResult(transport, new ArrayList<>(Arrays.asList(response)), null)); |
| processAllMessages(); |
| } |
| |
| // The purpose of this test is to make sure the network request insertion/removal works as |
| // expected, and make sure it is always sorted. |
| @Test |
| public void testCreateDataNetwork() throws Exception { |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| .build(), mPhone)); |
| |
| setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mInternetDataProfile, networkRequestList, |
| AccessNetworkConstants.TRANSPORT_TYPE_WWAN, |
| DataAllowedReason.NORMAL, mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); |
| |
| processAllMessages(); |
| verify(mSimulatedCommandsVerifier, never()).allocatePduSessionId(any(Message.class)); |
| verify(mMockedWwanDataServiceManager).setupDataCall(eq(AccessNetworkType.EUTRAN), |
| eq(mInternetDataProfile), eq(false), eq(false), |
| eq(DataService.REQUEST_REASON_NORMAL), nullable(LinkProperties.class), |
| eq(DataCallResponse.PDU_SESSION_ID_NOT_SET), nullable(NetworkSliceInfo.class), |
| any(TrafficDescriptor.class), eq(true), any(Message.class)); |
| assertThat(mDataNetworkUT.getId()).isEqualTo(123); |
| assertThat(networkRequestList.get(0).getState()) |
| .isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED); |
| LinkProperties lp = mDataNetworkUT.getLinkProperties(); |
| assertThat(lp.getAddresses()).containsExactly( |
| InetAddresses.parseNumericAddress(IPV4_ADDRESS), |
| InetAddresses.parseNumericAddress(IPV6_ADDRESS)); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(2)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList.get(0).getApnSetting()).isEqualTo(mInternetApnSetting); |
| assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING); |
| assertThat(pdcsList.get(0).getId()).isEqualTo(-1); |
| assertThat(pdcsList.get(0).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_LTE); |
| assertThat(pdcsList.get(0).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| assertThat(pdcsList.get(0).getLinkProperties()).isEqualTo(new LinkProperties()); |
| |
| assertThat(pdcsList.get(1).getApnSetting()).isEqualTo(mInternetApnSetting); |
| assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| assertThat(pdcsList.get(1).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(1).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_LTE); |
| assertThat(pdcsList.get(1).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| assertThat(pdcsList.get(1).getLinkProperties().getAddresses().get(0)) |
| .isEqualTo(InetAddresses.parseNumericAddress(IPV4_ADDRESS)); |
| assertThat(pdcsList.get(1).getLinkProperties().getAddresses().get(1)) |
| .isEqualTo(InetAddresses.parseNumericAddress(IPV6_ADDRESS)); |
| assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability( |
| NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue(); |
| assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability( |
| NetworkCapabilities.NET_CAPABILITY_SUPL)).isTrue(); |
| assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability( |
| NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue(); |
| |
| verify(mDataNetworkCallback).onConnected(eq(mDataNetworkUT)); |
| } |
| |
| @Test |
| public void testCreateDataNetworkOnEnterpriseSlice() throws Exception { |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE) |
| .build(), mPhone)); |
| |
| List<TrafficDescriptor> tds = List.of( |
| new TrafficDescriptor(null, new TrafficDescriptor.OsAppId( |
| TrafficDescriptor.OsAppId.ANDROID_OS_ID, "ENTERPRISE", 1).getBytes()), |
| new TrafficDescriptor(null, new TrafficDescriptor.OsAppId( |
| TrafficDescriptor.OsAppId.ANDROID_OS_ID, "ENTERPRISE", 5).getBytes()) |
| ); |
| setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123, tds); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mEnterpriseDataProfile, networkRequestList, |
| AccessNetworkConstants.TRANSPORT_TYPE_WWAN, DataAllowedReason.NORMAL, |
| mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); |
| |
| processAllMessages(); |
| |
| verify(mMockedWwanDataServiceManager).setupDataCall(eq(AccessNetworkType.EUTRAN), |
| eq(mEnterpriseDataProfile), eq(false), eq(false), |
| eq(DataService.REQUEST_REASON_NORMAL), nullable(LinkProperties.class), |
| eq(DataCallResponse.PDU_SESSION_ID_NOT_SET), nullable(NetworkSliceInfo.class), |
| any(TrafficDescriptor.class), eq(false), any(Message.class)); |
| |
| NetworkCapabilities nc = mDataNetworkUT.getNetworkCapabilities(); |
| assertThat(nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)).isTrue(); |
| assertThat(nc.getEnterpriseIds()).asList().containsExactly(1, 5); |
| } |
| |
| @Test |
| public void testCreateDataNetworkOnUrllcSlice() throws Exception { |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY) |
| .build(), mPhone)); |
| |
| List<TrafficDescriptor> tds = List.of( |
| new TrafficDescriptor(null, new TrafficDescriptor.OsAppId( |
| TrafficDescriptor.OsAppId.ANDROID_OS_ID, "PRIORITIZE_LATENCY", 1) |
| .getBytes()) |
| ); |
| setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123, tds); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mUrlccDataProfile, networkRequestList, |
| AccessNetworkConstants.TRANSPORT_TYPE_WWAN, DataAllowedReason.NORMAL, |
| mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); |
| |
| processAllMessages(); |
| |
| verify(mMockedWwanDataServiceManager).setupDataCall(eq(AccessNetworkType.EUTRAN), |
| eq(mUrlccDataProfile), eq(false), eq(false), |
| eq(DataService.REQUEST_REASON_NORMAL), nullable(LinkProperties.class), |
| eq(DataCallResponse.PDU_SESSION_ID_NOT_SET), nullable(NetworkSliceInfo.class), |
| any(TrafficDescriptor.class), eq(false), any(Message.class)); |
| |
| NetworkCapabilities nc = mDataNetworkUT.getNetworkCapabilities(); |
| assertThat(nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testCreateDataNetworkOnEmbbSlice() throws Exception { |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH) |
| .build(), mPhone)); |
| |
| List<TrafficDescriptor> tds = List.of( |
| new TrafficDescriptor(null, new TrafficDescriptor.OsAppId( |
| TrafficDescriptor.OsAppId.ANDROID_OS_ID, "PRIORITIZE_BANDWIDTH", 1) |
| .getBytes()) |
| ); |
| setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123, tds); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mEmbbDataProfile, networkRequestList, |
| AccessNetworkConstants.TRANSPORT_TYPE_WWAN, DataAllowedReason.NORMAL, |
| mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); |
| |
| processAllMessages(); |
| |
| verify(mMockedWwanDataServiceManager).setupDataCall(eq(AccessNetworkType.EUTRAN), |
| eq(mEmbbDataProfile), eq(false), eq(false), |
| eq(DataService.REQUEST_REASON_NORMAL), nullable(LinkProperties.class), |
| eq(DataCallResponse.PDU_SESSION_ID_NOT_SET), nullable(NetworkSliceInfo.class), |
| any(TrafficDescriptor.class), eq(false), any(Message.class)); |
| |
| NetworkCapabilities nc = mDataNetworkUT.getNetworkCapabilities(); |
| assertThat(nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)) |
| .isTrue(); |
| } |
| |
| // The purpose of this test is to make sure data could be torn down properly. |
| @Test |
| public void testTearDown() throws Exception { |
| testCreateDataNetwork(); |
| sendTearDownEvent(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 123, |
| DataFailCause.EMM_DETACHED); |
| |
| verify(mSimulatedCommandsVerifier, never()).releasePduSessionId(nullable(Message.class), |
| anyInt()); |
| verify(mMockedWwanDataServiceManager).deactivateDataCall(eq(123), |
| eq(DataService.REQUEST_REASON_NORMAL), any(Message.class)); |
| verify(mDataNetworkCallback).onDisconnected(eq(mDataNetworkUT), eq( |
| DataFailCause.EMM_DETACHED)); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList.get(2).getApnSetting()).isEqualTo(mInternetApnSetting); |
| assertThat(pdcsList.get(2).getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING); |
| assertThat(pdcsList.get(2).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(2).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_LTE); |
| assertThat(pdcsList.get(2).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| |
| assertThat(pdcsList.get(3).getApnSetting()).isEqualTo(mInternetApnSetting); |
| assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED); |
| assertThat(pdcsList.get(3).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(3).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_LTE); |
| assertThat(pdcsList.get(3).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| } |
| |
| @Test |
| public void testCreateDataNetworkOnIwlan() throws Exception { |
| doReturn(mIwlanNetworkRegistrationInfo).when(mServiceState).getNetworkRegistrationInfo( |
| eq(NetworkRegistrationInfo.DOMAIN_PS), |
| eq(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)); |
| doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager) |
| .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS); |
| |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) |
| .build(), mPhone)); |
| |
| setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 123); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mImsDataProfile, networkRequestList, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, |
| DataAllowedReason.NORMAL, mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN); |
| |
| processAllMessages(); |
| verify(mSimulatedCommandsVerifier).allocatePduSessionId(any(Message.class)); |
| verify(mMockedWlanDataServiceManager).setupDataCall(eq(AccessNetworkType.IWLAN), |
| eq(mImsDataProfile), eq(false), eq(false), |
| eq(DataService.REQUEST_REASON_NORMAL), nullable(LinkProperties.class), |
| eq(1), nullable(NetworkSliceInfo.class), |
| any(TrafficDescriptor.class), eq(true), any(Message.class)); |
| assertThat(mDataNetworkUT.getId()).isEqualTo(123); |
| assertThat(networkRequestList.get(0).getState()) |
| .isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED); |
| LinkProperties lp = mDataNetworkUT.getLinkProperties(); |
| assertThat(lp.getAddresses()).containsExactly( |
| InetAddresses.parseNumericAddress(IPV4_ADDRESS), |
| InetAddresses.parseNumericAddress(IPV6_ADDRESS)); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(2)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList.get(0).getApnSetting()).isEqualTo(mImsApnSetting); |
| assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING); |
| assertThat(pdcsList.get(0).getId()).isEqualTo(-1); |
| assertThat(pdcsList.get(0).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_IWLAN); |
| assertThat(pdcsList.get(0).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); |
| assertThat(pdcsList.get(0).getLinkProperties()).isEqualTo(new LinkProperties()); |
| |
| assertThat(pdcsList.get(1).getApnSetting()).isEqualTo(mImsApnSetting); |
| assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| assertThat(pdcsList.get(1).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(1).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_IWLAN); |
| assertThat(pdcsList.get(1).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); |
| assertThat(pdcsList.get(1).getLinkProperties().getAddresses()).containsExactly( |
| InetAddresses.parseNumericAddress(IPV4_ADDRESS), |
| InetAddresses.parseNumericAddress(IPV6_ADDRESS)); |
| |
| assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability( |
| NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue(); |
| assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability( |
| NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isFalse(); |
| |
| verify(mDataNetworkCallback).onConnected(eq(mDataNetworkUT)); |
| } |
| |
| @Test |
| public void testTearDownIwlan() throws Exception { |
| testCreateDataNetworkOnIwlan(); |
| sendTearDownEvent(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 123, |
| DataFailCause.EMM_DETACHED); |
| |
| verify(mSimulatedCommandsVerifier).releasePduSessionId(nullable(Message.class), eq(1)); |
| verify(mMockedWlanDataServiceManager).deactivateDataCall(eq(123), |
| eq(DataService.REQUEST_REASON_NORMAL), any(Message.class)); |
| verify(mDataNetworkCallback).onDisconnected(eq(mDataNetworkUT), eq( |
| DataFailCause.EMM_DETACHED)); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList.get(2).getApnSetting()).isEqualTo(mImsApnSetting); |
| assertThat(pdcsList.get(2).getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING); |
| assertThat(pdcsList.get(2).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(2).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_IWLAN); |
| assertThat(pdcsList.get(2).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); |
| |
| assertThat(pdcsList.get(3).getApnSetting()).isEqualTo(mImsApnSetting); |
| assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED); |
| assertThat(pdcsList.get(3).getId()).isEqualTo(123); |
| assertThat(pdcsList.get(3).getNetworkType()).isEqualTo(TelephonyManager.NETWORK_TYPE_IWLAN); |
| assertThat(pdcsList.get(3).getTransportType()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); |
| } |
| |
| @Test |
| public void testHandover() throws Exception { |
| testCreateDataNetwork(); |
| |
| setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 456); |
| // Now handover to IWLAN |
| mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null); |
| processAllMessages(); |
| |
| verify(mLinkBandwidthEstimator).unregisterForBandwidthChanged( |
| eq(mDataNetworkUT.getHandler())); |
| assertThat(mDataNetworkUT.getTransport()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); |
| assertThat(mDataNetworkUT.getId()).isEqualTo(456); |
| verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT)); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList).hasSize(4); |
| assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING); |
| assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| assertThat(pdcsList.get(2).getState()) |
| .isEqualTo(TelephonyManager.DATA_HANDOVER_IN_PROGRESS); |
| assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| |
| // Now handover back to cellular |
| Mockito.clearInvocations(mDataNetworkCallback); |
| Mockito.clearInvocations(mLinkBandwidthEstimator); |
| mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, null); |
| processAllMessages(); |
| |
| verify(mLinkBandwidthEstimator).registerForBandwidthChanged( |
| eq(mDataNetworkUT.getHandler()), anyInt(), eq(null)); |
| assertThat(mDataNetworkUT.getTransport()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| assertThat(mDataNetworkUT.getId()).isEqualTo(123); |
| verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT)); |
| } |
| |
| @Test |
| public void testHandoverFailed() throws Exception { |
| testCreateDataNetwork(); |
| |
| setFailedSetupDataResponse(mMockedWlanDataServiceManager, |
| DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE); |
| // Now attempt to handover to IWLAN but fail it. |
| mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null); |
| processAllMessages(); |
| |
| verify(mDataNetworkCallback).onHandoverFailed(eq(mDataNetworkUT), |
| eq(DataFailCause.SERVICE_TEMPORARILY_UNAVAILABLE), eq(-1L), |
| eq(DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY)); |
| verify(mLinkBandwidthEstimator, never()).unregisterForBandwidthChanged( |
| eq(mDataNetworkUT.getHandler())); |
| assertThat(mDataNetworkUT.getTransport()) |
| .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); |
| assertThat(mDataNetworkUT.getId()).isEqualTo(123); |
| |
| ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = |
| ArgumentCaptor.forClass(PreciseDataConnectionState.class); |
| verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture()); |
| List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues(); |
| |
| assertThat(pdcsList).hasSize(4); |
| assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING); |
| assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| assertThat(pdcsList.get(2).getState()) |
| .isEqualTo(TelephonyManager.DATA_HANDOVER_IN_PROGRESS); |
| assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED); |
| assertThat(pdcsList.get(3).getLastCauseCode()) |
| .isEqualTo(DataFailCause.SERVICE_TEMPORARILY_UNAVAILABLE); |
| } |
| |
| @Test |
| public void testAdminAndOwnerUids() throws Exception { |
| DataNetworkController.NetworkRequestList |
| networkRequestList = new DataNetworkController.NetworkRequestList(); |
| networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| .build(), mPhone)); |
| |
| setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123); |
| doReturn(ADMIN_UID2).when(mCarrierPrivilegesTracker).getCarrierServicePackageUid(); |
| |
| mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers, |
| mInternetDataProfile, networkRequestList, |
| AccessNetworkConstants.TRANSPORT_TYPE_WWAN, |
| DataAllowedReason.NORMAL, mDataNetworkCallback); |
| replaceInstance(DataNetwork.class, "mDataCallSessionStats", |
| mDataNetworkUT, mDataCallSessionStats); |
| mDataNetworkUT.sendMessage(18/*EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED*/, |
| new AsyncResult(null, new int[]{ADMIN_UID1, ADMIN_UID2}, null)); |
| |
| sendServiceStateChangedEvent(ServiceState.STATE_IN_SERVICE, |
| ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); |
| processAllMessages(); |
| |
| assertThat(mDataNetworkUT.getNetworkCapabilities().getAdministratorUids()).asList() |
| .containsExactly(ADMIN_UID1, ADMIN_UID2); |
| assertThat(mDataNetworkUT.getNetworkCapabilities().getOwnerUid()).isEqualTo(ADMIN_UID2); |
| } |
| |
| @Test |
| public void testDeactivateDataCallRadioNotAvailable() throws Exception { |
| testCreateDataNetwork(); |
| assertThat(mDataNetworkUT.isConnected()).isTrue(); |
| mDataNetworkUT.sendMessage(19/*EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE*/, |
| 6/*RESULT_ERROR_RADIO_NOT_AVAILABLE*/); |
| processAllMessages(); |
| |
| verify(mDataNetworkCallback).onDisconnected(eq(mDataNetworkUT), eq( |
| DataFailCause.RADIO_NOT_AVAILABLE)); |
| assertThat(mDataNetworkUT.isConnected()).isFalse(); |
| } |
| } |