blob: 0078277aa78374022de402562a40bf0ab1193ab9 [file] [log] [blame]
/*
* 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.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
import static com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
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 static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.InetAddresses;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener;
import android.net.vcn.VcnNetworkPolicyResult;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.provider.Telephony;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.NetCapability;
import android.telephony.Annotation.NetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.DataFailCause;
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.LteVopsSupportInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkRegistrationInfo.RegistrationState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyProtoEnums;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataCallResponse.LinkStatus;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
import android.telephony.data.ThrottleStatus;
import android.telephony.data.TrafficDescriptor;
import android.telephony.data.TrafficDescriptor.OsAppId;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.ImsStateCallback;
import android.telephony.ims.RegistrationManager.RegistrationCallback;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.MultiSimSettingController;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataEvaluation.DataDisallowedReason;
import com.android.internal.telephony.data.DataNetworkController.HandoverRule;
import com.android.internal.telephony.data.DataRetryManager.DataRetryManagerCallback;
import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
import com.android.internal.telephony.ims.ImsResolver;
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.lang.reflect.Field;
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class DataNetworkControllerTest 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 String FAKE_MMTEL_PACKAGE = "fake.mmtel.package";
private static final String FAKE_RCS_PACKAGE = "fake.rcs.package";
// Mocked classes
private PhoneSwitcher mMockedPhoneSwitcher;
protected ISub mMockedIsub;
private DataNetworkControllerCallback mMockedDataNetworkControllerCallback;
private DataRetryManagerCallback mMockedDataRetryManagerCallback;
private ImsResolver mMockedImsResolver;
private ImsManager mMockedImsManager;
private ImsMmTelManager mMockedImsMmTelManager;
private ImsRcsManager mMockedImsRcsManager;
private ImsStateCallback mMmtelStateCallback;
private ImsStateCallback mRcsStateCallback;
private RegistrationCallback mMmtelRegCallback;
private RegistrationCallback mRcsRegCallback;
private SubscriptionInfo mMockSubInfo;
private int mNetworkRequestId = 0;
private final SparseArray<DataServiceManager> mMockedDataServiceManagers = new SparseArray<>();
private final SparseArray<RegistrantList> mDataCallListChangedRegistrants = new SparseArray<>();
private DataNetworkController mDataNetworkControllerUT;
private PersistableBundle mCarrierConfig;
private AccessNetworksManagerCallback mAccessNetworksManagerCallback;
private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback;
private final DataProfile mGeneralPurposeDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setId(2163)
.setOperatorNumeric("12345")
.setEntryName("internet_supl_mms_apn")
.setApnName("internet_supl_mms_apn")
.setUser("user")
.setPassword("passwd")
.setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL
| ApnSetting.TYPE_MMS)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IP)
.setCarrierEnabled(true)
.setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN
| TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT))
.setLingeringNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
| TelephonyManager.NETWORK_TYPE_BITMASK_NR))
.setProfileId(1234)
.setMaxConns(321)
.setWaitTime(456)
.setMaxConnsTime(789)
.build())
.setPreferred(false)
.build();
private final DataProfile mImsCellularDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setId(2164)
.setOperatorNumeric("12345")
.setEntryName("ims_apn")
.setApnName("ims_apn")
.setUser("user")
.setPassword("passwd")
.setApnTypeBitmask(ApnSetting.TYPE_IMS)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IP)
.setCarrierEnabled(true)
.setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT))
.setLingeringNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
| TelephonyManager.NETWORK_TYPE_BITMASK_NR))
.setProfileId(1235)
.setMaxConns(321)
.setWaitTime(456)
.setMaxConnsTime(789)
.build())
.setPreferred(false)
.build();
private final DataProfile mImsIwlanDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setId(2164)
.setOperatorNumeric("12345")
.setEntryName("ims_apn")
.setApnName("ims_apn")
.setUser("user")
.setPassword("passwd")
.setApnTypeBitmask(ApnSetting.TYPE_IMS)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IPV6)
.setCarrierEnabled(true)
.setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN))
.setProfileId(1235)
.setMaxConns(321)
.setWaitTime(456)
.setMaxConnsTime(789)
.build())
.setPreferred(false)
.build();
private final DataProfile mEmergencyDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setEntryName("DEFAULT EIMS")
.setId(2165)
.setProtocol(ApnSetting.PROTOCOL_IPV4V6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
.setApnName("sos")
.setApnTypeBitmask(ApnSetting.TYPE_EMERGENCY)
.setCarrierEnabled(true)
.setApnSetId(Telephony.Carriers.MATCH_ALL_APN_SET_ID)
.build())
.build();
private final DataProfile mFotaDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setId(2166)
.setOperatorNumeric("12345")
.setEntryName("fota_apn")
.setApnName("fota_apn")
.setUser("user")
.setPassword("passwd")
.setApnTypeBitmask(ApnSetting.TYPE_FOTA)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IP)
.setCarrierEnabled(true)
.setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT)
.setProfileId(1236)
.setMaxConns(321)
.setWaitTime(456)
.setMaxConnsTime(789)
.build())
.setPreferred(false)
.build();
private final DataProfile mTetheringDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setId(2167)
.setOperatorNumeric("12345")
.setEntryName("dun_apn")
.setApnName("dun_apn")
.setUser("user")
.setPassword("passwd")
.setApnTypeBitmask(ApnSetting.TYPE_DUN)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IP)
.setCarrierEnabled(true)
.setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT)
.setProfileId(1236)
.setMaxConns(321)
.setWaitTime(456)
.setMaxConnsTime(789)
.build())
.setPreferred(false)
.build();
private final DataProfile mEnterpriseDataProfile = new DataProfile.Builder()
.setTrafficDescriptor(new TrafficDescriptor(null,
new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID,
"ENTERPRISE", 1).getBytes()))
.build();
/** Data call response map. The first key is the transport type, the second key is the cid. */
private final Map<Integer, Map<Integer, DataCallResponse>> mDataCallResponses = new HashMap<>();
private @NonNull DataCallResponse createDataCallResponse(int cid, @LinkStatus int linkStatus) {
return createDataCallResponse(cid, linkStatus, Collections.emptyList());
}
private @NonNull DataCallResponse createDataCallResponse(int cid, @LinkStatus int linkStatus,
@NonNull List<TrafficDescriptor> tdList) {
return new DataCallResponse.Builder()
.setCause(0)
.setRetryDurationMillis(-1L)
.setId(cid)
.setLinkStatus(linkStatus)
.setProtocolType(ApnSetting.PROTOCOL_IPV4V6)
.setInterfaceName("ifname" + cid)
.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(tdList)
.build();
}
private void setFailedSetupDataResponse(DataServiceManager dsm, @DataFailureCause int cause,
long retryMillis, boolean forHandover) {
setFailedSetupDataResponse(dsm, cause, retryMillis, forHandover, 0);
}
private void setFailedSetupDataResponse(DataServiceManager dsm, @DataFailureCause int cause,
long retryMillis, boolean forHandover, long delay) {
doAnswer(invocation -> {
final Message msg = (Message) invocation.getArguments()[10];
DataCallResponse response = new DataCallResponse.Builder()
.setCause(cause)
.setRetryDurationMillis(retryMillis)
.setHandoverFailureMode(
DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER)
.build();
msg.getData().putParcelable("data_call_response", response);
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.getTarget().sendMessageDelayed(msg, delay);
return null;
}).when(dsm).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(),
anyBoolean(), forHandover ? eq(DataService.REQUEST_REASON_HANDOVER)
: eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(),
anyBoolean(), any(Message.class));
}
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, DataCallResponse response) {
doAnswer(invocation -> {
final Message msg = (Message) invocation.getArguments()[10];
int transport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
if (dsm == mMockedWwanDataServiceManager) {
transport = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
} else if (dsm == mMockedWlanDataServiceManager) {
transport = AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
}
mDataCallResponses.computeIfAbsent(transport, v -> new HashMap<>());
mDataCallResponses.get(transport).put(response.getId(), response);
msg.getData().putParcelable("data_call_response", response);
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.sendToTarget();
mDataCallListChangedRegistrants.get(transport).notifyRegistrants(
new AsyncResult(transport, new ArrayList<>(mDataCallResponses.get(
transport).values()), null));
return null;
}).when(dsm).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(),
anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
any(Message.class));
}
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid) {
setSuccessfulSetupDataResponse(dsm, cid, 0L);
}
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid, long delay) {
doAnswer(invocation -> {
final Message msg = (Message) invocation.getArguments()[10];
DataCallResponse response = createDataCallResponse(cid,
DataCallResponse.LINK_STATUS_ACTIVE);
int transport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
if (dsm == mMockedWwanDataServiceManager) {
transport = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
} else if (dsm == mMockedWlanDataServiceManager) {
transport = AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
}
mDataCallResponses.computeIfAbsent(transport, v -> new HashMap<>());
mDataCallResponses.get(transport).put(cid, response);
msg.getData().putParcelable("data_call_response", response);
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.getTarget().sendMessageDelayed(msg, delay);
final int t = transport;
msg.getTarget().postDelayed(() -> {
mDataCallListChangedRegistrants.get(t).notifyRegistrants(
new AsyncResult(t, new ArrayList<>(mDataCallResponses.get(
t).values()), null));
}, delay + 100);
return null;
}).when(dsm).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(),
anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
any(Message.class));
}
private void clearCallbacks() throws Exception {
Field field = DataNetworkController.class
.getDeclaredField("mDataNetworkControllerCallbacks");
field.setAccessible(true);
((Set<DataNetworkControllerCallback>) field.get(mDataNetworkControllerUT)).clear();
}
private void carrierConfigChanged() {
// Trigger carrier config reloading
Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
mContext.sendBroadcast(intent);
processAllMessages();
}
private void setImsRegistered(boolean registered) {
if (registered) {
final ArraySet<String> features = new ArraySet<>();
features.add("feature1");
features.add("feature2");
ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build();
mMmtelRegCallback.onRegistered(attr);
} else {
ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, "");
mMmtelRegCallback.onUnregistered(info);
}
}
private void setRcsRegistered(boolean registered) {
if (registered) {
final ArraySet<String> features = new ArraySet<>();
features.add("feature1");
features.add("feature2");
ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build();
mRcsRegCallback.onRegistered(attr);
} else {
ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, "");
mRcsRegCallback.onUnregistered(info);
}
}
private void serviceStateChanged(@NetworkType int networkType,
@RegistrationState int regState) {
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
serviceStateChanged(networkType, regState, regState,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
}
private void serviceStateChanged(@NetworkType int networkType,
@RegistrationState int regState, DataSpecificRegistrationInfo dsri) {
serviceStateChanged(networkType, regState, regState,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
}
private void serviceStateChanged(@NetworkType int networkType,
@RegistrationState int dataRegState, @RegistrationState int voiceRegState,
@RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri) {
if (dsri == null) {
dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
}
ServiceState ss = new ServiceState();
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(networkType)
.setRegistrationState(dataRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(iwlanRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(networkType)
.setRegistrationState(voiceRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
ss.setDataRoamingFromRegistration(dataRegState
== NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
}
// set SS reg state base on SST impl, where WLAN overrides WWAN's data reg.
private void processServiceStateRegStateForTest(ServiceState ss) {
int wlanRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN).getRegistrationState();
if (wlanRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
ss.setDataRegState(ServiceState.STATE_IN_SERVICE);
} else {
int cellularRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getRegistrationState();
int dataState = (cellularRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME
|| cellularRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING)
? ServiceState.STATE_IN_SERVICE : ServiceState.STATE_OUT_OF_SERVICE;
ss.setDataRegState(dataState);
}
int voiceRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getRegistrationState();
int voiceState = (voiceRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME
|| voiceRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING)
? ServiceState.STATE_IN_SERVICE : ServiceState.STATE_OUT_OF_SERVICE;
ss.setVoiceRegState(voiceState);
}
private void updateTransport(@NetCapability int capability, @TransportType int transport) {
doReturn(transport).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(capability);
mAccessNetworksManagerCallback.onPreferredTransportChanged(capability);
processAllMessages();
}
private void setVcnManagerPolicy(boolean vcnManaged, boolean shouldTearDown) {
doAnswer(invocation -> {
final NetworkCapabilities networkCapabilities =
(NetworkCapabilities) invocation.getArguments()[0];
if (vcnManaged) {
networkCapabilities.removeCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
} else {
networkCapabilities.addCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
}
return new VcnNetworkPolicyResult(
shouldTearDown, networkCapabilities);
}).when(mVcnManager).applyVcnNetworkPolicy(any(NetworkCapabilities.class),
any(LinkProperties.class));
}
private void initializeConfig() {
mCarrierConfig = mContextFixture.getCarrierConfigBundle();
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY,
new String[]{
"eims:90", "supl:80", "mms:70", "xcap:70", "cbs:50", "mcx:50", "fota:50",
"ims:40", "dun:30", "enterprise:20", "internet:20"
});
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_TELEPHONY_DATA_SETUP_RETRY_RULES_STRING_ARRAY,
new String[]{
"capabilities=eims, retry_interval=1000, maximum_retries=20",
"fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|"
+ "2254, maximum_retries=0", // No retry for those causes
"capabilities=mms|supl|cbs, retry_interval=2000",
"capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
+ "5000|10000|15000|20000|40000|60000|120000|240000|"
+ "600000|1200000|1800000, maximum_retries=20"
});
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY,
new String[] {"retry_interval=1000|2000|4000|8000|16000, maximum_retries=5"
});
mCarrierConfig.putInt(CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 1234);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL,
true);
mCarrierConfig.putIntArray(CarrierConfigManager.KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
new int[]{TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT,
TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A,
TelephonyManager.NETWORK_TYPE_EVDO_B});
mContextFixture.putResource(com.android.internal.R.string.config_bandwidthEstimateSource,
"bandwidth_estimator");
mContextFixture.putIntResource(com.android.internal.R.integer
.config_delay_for_ims_dereg_millis, 3000);
mContextFixture.putBooleanResource(com.android.internal.R.bool
.config_enable_iwlan_handover_policy, true);
mContextFixture.putBooleanResource(com.android.internal.R.bool
.config_enhanced_iwlan_handover_check, true);
}
@Before
public void setUp() throws Exception {
logd("DataNetworkControllerTest +Setup!");
super.setUp(getClass().getSimpleName());
mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
mMockedIsub = Mockito.mock(ISub.class);
mMockedImsManager = mContext.getSystemService(ImsManager.class);
mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class);
mMockedImsRcsManager = Mockito.mock(ImsRcsManager.class);
mMockedImsResolver = Mockito.mock(ImsResolver.class);
mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class);
mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class);
mMockSubInfo = Mockito.mock(SubscriptionInfo.class);
when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class),
any(DataNetworkController.class), any(Looper.class),
any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod();
doReturn(mMockedImsMmTelManager).when(mMockedImsManager).getImsMmTelManager(anyInt());
doReturn(mMockedImsRcsManager).when(mMockedImsManager).getImsRcsManager(anyInt());
initializeConfig();
mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
mMockedWwanDataServiceManager);
mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
mMockedWlanDataServiceManager);
replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doReturn(1).when(mMockedIsub).getDefaultDataSubId();
doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
doReturn(mPhone).when(mPhone).getImsPhone();
mServiceManagerMockedServices.put("isub", mIBinder);
doReturn(new SubscriptionPlan[]{}).when(mNetworkPolicyManager)
.getSubscriptionPlans(anyInt(), any());
doReturn(true).when(mSST).getDesiredPowerState();
doReturn(true).when(mSST).getPowerStateFromCarrier();
doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed();
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn("").when(mSubscriptionController).getDataEnabledOverrideRules(anyInt());
doReturn(true).when(mSubscriptionController).setDataEnabledOverrideRules(
anyInt(), anyString());
List<SubscriptionInfo> infoList = new ArrayList<>();
infoList.add(mMockSubInfo);
doReturn(infoList).when(mSubscriptionController).getSubscriptionsInGroup(
any(), any(), any());
doReturn(true).when(mSubscriptionController).isActiveSubId(anyInt());
doReturn(0).when(mSubscriptionController).getPhoneId(anyInt());
for (int transport : new int[]{AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN}) {
mDataCallListChangedRegistrants.put(transport, new RegistrantList());
setSuccessfulSetupDataResponse(mMockedDataServiceManagers.get(transport), 1);
doAnswer(invocation -> {
int cid = (int) invocation.getArguments()[0];
Message msg = (Message) invocation.getArguments()[2];
msg.sendToTarget();
mDataCallResponses.get(transport).remove(cid);
mDataCallListChangedRegistrants.get(transport).notifyRegistrants(
new AsyncResult(transport, new ArrayList<>(mDataCallResponses.get(
transport).values()), null));
return null;
}).when(mMockedDataServiceManagers.get(transport)).deactivateDataCall(
anyInt(), anyInt(), any(Message.class));
doAnswer(invocation -> {
Handler h = (Handler) invocation.getArguments()[0];
int what = (int) invocation.getArguments()[1];
mDataCallListChangedRegistrants.get(transport).addUnique(h, what, transport);
return null;
}).when(mMockedDataServiceManagers.get(transport)).registerForDataCallListChanged(any(
Handler.class), anyInt());
}
doReturn(-1).when(mPhone).getSubId();
// Note that creating a "real" data network controller will also result in creating
// real DataRetryManager, DataConfigManager, etc...Normally in unit test we should isolate
// other modules and make them mocked, but only focusing on testing the unit we would like
// to test, in this case, DataNetworkController. But since there are too many interactions
// between DataNetworkController and its sub-modules, we intend to make those modules "real"
// as well, except some modules below we replaced with mocks.
mDataNetworkControllerUT = new DataNetworkController(mPhone, Looper.myLooper());
doReturn(mDataNetworkControllerUT).when(mPhone).getDataNetworkController();
doReturn(1).when(mPhone).getSubId();
mDataNetworkControllerUT.obtainMessage(15/*EVENT_SUBSCRIPTION_CHANGED*/).sendToTarget();
processAllMessages();
// Clear the callbacks created by the real sub-modules created by DataNetworkController.
clearCallbacks();
SparseArray<DataServiceManager> dataServiceManagers = new SparseArray<>();
dataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
mMockedWwanDataServiceManager);
dataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
mMockedWlanDataServiceManager);
replaceInstance(DataNetworkController.class, "mDataServiceManagers",
mDataNetworkControllerUT, dataServiceManagers);
replaceInstance(DataNetworkController.class, "mDataProfileManager",
mDataNetworkControllerUT, mDataProfileManager);
replaceInstance(DataNetworkController.class, "mAccessNetworksManager",
mDataNetworkControllerUT, mAccessNetworksManager);
replaceInstance(ImsResolver.class, "sInstance", null, mMockedImsResolver);
ArgumentCaptor<AccessNetworksManagerCallback> callbackCaptor =
ArgumentCaptor.forClass(AccessNetworksManagerCallback.class);
verify(mAccessNetworksManager).registerCallback(callbackCaptor.capture());
mAccessNetworksManagerCallback = callbackCaptor.getValue();
ArgumentCaptor<LinkBandwidthEstimatorCallback> linkBandwidthEstimatorCallbackCaptor =
ArgumentCaptor.forClass(LinkBandwidthEstimatorCallback.class);
verify(mLinkBandwidthEstimator).registerCallback(
linkBandwidthEstimatorCallbackCaptor.capture());
mLinkBandwidthEstimatorCallback = linkBandwidthEstimatorCallbackCaptor.getValue();
List<DataProfile> profiles = List.of(mGeneralPurposeDataProfile,
mImsCellularDataProfile,
mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile,
mTetheringDataProfile);
doAnswer(invocation -> {
TelephonyNetworkRequest networkRequest =
(TelephonyNetworkRequest) invocation.getArguments()[0];
int networkType = (int) invocation.getArguments()[1];
for (DataProfile dataProfile : profiles) {
if (dataProfile.canSatisfy(networkRequest.getCapabilities())
&& (dataProfile.getApnSetting().getNetworkTypeBitmask() == 0
|| (dataProfile.getApnSetting().getNetworkTypeBitmask()
& ServiceState.getBitmaskForTech(networkType)) != 0)) {
return dataProfile;
}
}
logd("Cannot find data profile to satisfy " + networkRequest + ", network type="
+ TelephonyManager.getNetworkTypeName(networkType));
return null;
}).when(mDataProfileManager).getDataProfileForNetworkRequest(
any(TelephonyNetworkRequest.class), anyInt());
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(anyInt());
doReturn(true).when(mDataProfileManager).isDataProfilePreferred(any(DataProfile.class));
doAnswer(invocation -> {
String apnName = (String) invocation.getArguments()[0];
TrafficDescriptor td = (TrafficDescriptor) invocation.getArguments()[1];
List<DataProfile> dps = profiles;
if (td != null) {
dps = dps.stream()
.filter(dp -> td.equals(dp.getTrafficDescriptor()))
.collect(Collectors.toList());
}
if (apnName != null) {
dps = dps.stream()
.filter(dp -> dp.getApnSetting() != null)
.filter(dp -> apnName.equals(dp.getApnSetting().getApnName()))
.collect(Collectors.toList());
}
return dps.isEmpty() ? null : dps.get(0);
}).when(mDataProfileManager).getDataProfile(anyString(), any());
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
return null;
}).when(mMockedDataNetworkControllerCallback).invokeFromExecutor(any(Runnable.class));
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
return null;
}).when(mMockedDataRetryManagerCallback).invokeFromExecutor(any(Runnable.class));
mDataNetworkControllerUT.registerDataNetworkControllerCallback(
mMockedDataNetworkControllerCallback);
mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
10/*SIM_STATE_LOADED*/, 0).sendToTarget();
mDataNetworkControllerUT.obtainMessage(8/*EVENT_DATA_SERVICE_BINDING_CHANGED*/,
new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, true, null))
.sendToTarget();
mDataNetworkControllerUT.obtainMessage(8/*EVENT_DATA_SERVICE_BINDING_CHANGED*/,
new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, true, null))
.sendToTarget();
ArgumentCaptor<ImsStateCallback> imsCallbackCaptor =
ArgumentCaptor.forClass(ImsStateCallback.class);
verify(mMockedImsMmTelManager).registerImsStateCallback(any(Executor.class),
imsCallbackCaptor.capture());
mMmtelStateCallback = imsCallbackCaptor.getValue();
verify(mMockedImsRcsManager).registerImsStateCallback(any(Executor.class),
imsCallbackCaptor.capture());
mRcsStateCallback = imsCallbackCaptor.getValue();
carrierConfigChanged();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
// IMS registration
doReturn(FAKE_MMTEL_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName(
anyInt(), eq(ImsFeature.FEATURE_MMTEL));
doReturn(FAKE_RCS_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName(
anyInt(), eq(ImsFeature.FEATURE_RCS));
mMmtelStateCallback.onAvailable();
mRcsStateCallback.onAvailable();
ArgumentCaptor<RegistrationCallback> regCallbackCaptor =
ArgumentCaptor.forClass(RegistrationCallback.class);
verify(mMockedImsMmTelManager).registerImsRegistrationCallback(any(Executor.class),
regCallbackCaptor.capture());
mMmtelRegCallback = regCallbackCaptor.getValue();
verify(mMockedImsRcsManager).registerImsRegistrationCallback(any(Executor.class),
regCallbackCaptor.capture());
mRcsRegCallback = regCallbackCaptor.getValue();
processAllMessages();
logd("DataNetworkControllerTest -Setup!");
}
@After
public void tearDown() throws Exception {
logd("tearDown");
mMockedDataServiceManagers.clear();
mDataCallListChangedRegistrants.clear();
mDataNetworkControllerUT = null;
mCarrierConfig = null;
super.tearDown();
}
private @NonNull TelephonyNetworkRequest createNetworkRequest(Integer... capabilities) {
NetworkCapabilities netCaps = new NetworkCapabilities();
for (int networkCapability : capabilities) {
netCaps.addCapability(networkCapability);
}
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
return new TelephonyNetworkRequest(nativeNetworkRequest, mPhone);
}
// 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 testNetworkRequestList() {
NetworkRequestList networkRequestList = new NetworkRequestList();
TelephonyNetworkRequest internetNetworkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_INTERNET);
TelephonyNetworkRequest eimsNetworkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_EIMS);
TelephonyNetworkRequest mmsNetworkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_MMS);
networkRequestList.add(internetNetworkRequest);
networkRequestList.add(eimsNetworkRequest);
networkRequestList.add(mmsNetworkRequest);
// Check if emergency has the highest priority, then mms, then internet.
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_EIMS);
assertThat(networkRequestList.get(1).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_MMS);
assertThat(networkRequestList.get(2).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Add IMS
TelephonyNetworkRequest imsNetworkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_IMS);
assertThat(networkRequestList.add(imsNetworkRequest)).isTrue();
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_EIMS);
assertThat(networkRequestList.get(1).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_MMS);
assertThat(networkRequestList.get(2).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_IMS);
assertThat(networkRequestList.get(3).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Add IMS again
assertThat(networkRequestList.add(imsNetworkRequest)).isFalse();
assertThat(networkRequestList.size()).isEqualTo(4);
// Remove MMS
assertThat(networkRequestList.remove(mmsNetworkRequest)).isTrue();
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_EIMS);
assertThat(networkRequestList.get(1).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_IMS);
assertThat(networkRequestList.get(2).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Remove EIMS
assertThat(networkRequestList.remove(eimsNetworkRequest)).isTrue();
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_IMS);
assertThat(networkRequestList.get(1).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Remove Internet
assertThat(networkRequestList.remove(internetNetworkRequest)).isTrue();
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_IMS);
// Remove XCAP (which does not exist)
assertThat(networkRequestList.remove(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_XCAP))).isFalse();
assertThat(networkRequestList.get(0).getCapabilities()[0])
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_IMS);
// Remove IMS
assertThat(networkRequestList.remove(imsNetworkRequest)).isTrue();
assertThat(networkRequestList).isEmpty();
}
private @NonNull List<DataNetwork> getDataNetworks() throws Exception {
Field field = DataNetworkController.class.getDeclaredField("mDataNetworkList");
field.setAccessible(true);
return (List<DataNetwork>) field.get(mDataNetworkControllerUT);
}
private void verifyInternetConnected() throws Exception {
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any());
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
private void verifyConnectedNetworkHasCapabilities(@NetCapability int... networkCapabilities)
throws Exception {
List<DataNetwork> dataNetworkList = getDataNetworks();
for (DataNetwork dataNetwork : getDataNetworks()) {
if (dataNetwork.isConnected() && Arrays.stream(networkCapabilities).boxed()
.allMatch(dataNetwork.getNetworkCapabilities()::hasCapability)) {
return;
}
}
fail("No network with " + DataUtils.networkCapabilitiesToString(networkCapabilities)
+ " is connected. dataNetworkList=" + dataNetworkList);
}
private void verifyNoConnectedNetworkHasCapability(@NetCapability int networkCapability)
throws Exception {
for (DataNetwork dataNetwork : getDataNetworks()) {
assertWithMessage("Network " + dataNetwork + " should not be connected.")
.that(dataNetwork.isConnected() && dataNetwork.getNetworkCapabilities()
.hasCapability(networkCapability)).isFalse();
}
}
private void verifyConnectedNetworkHasDataProfile(@NonNull DataProfile dataProfile)
throws Exception {
List<DataNetwork> dataNetworkList = getDataNetworks();
for (DataNetwork dataNetwork : getDataNetworks()) {
if (dataNetwork.isConnected() && dataNetwork.getDataProfile().equals(dataProfile)) {
return;
}
}
fail("No network with " + dataProfile + " is connected. dataNetworkList="
+ dataNetworkList);
}
private void verifyAllDataDisconnected() throws Exception {
List<DataNetwork> dataNetworkList = getDataNetworks();
assertWithMessage("All data should be disconnected but it's not. " + dataNetworkList)
.that(dataNetworkList).isEmpty();
}
// To test the basic data setup. Copy this as example for other tests.
@Test
public void testSetupDataNetwork() throws Exception {
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
DataNetwork dataNetwork = dataNetworkList.get(0);
assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly(
InetAddresses.parseNumericAddress(IPV4_ADDRESS),
InetAddresses.parseNumericAddress(IPV6_ADDRESS));
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any());
}
@Test
public void testSetupImsDataNetwork() throws Exception {
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
verifyConnectedNetworkHasDataProfile(mImsCellularDataProfile);
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly(
InetAddresses.parseNumericAddress(IPV4_ADDRESS),
InetAddresses.parseNumericAddress(IPV6_ADDRESS));
}
@Test
public void testSetupEnterpriseDataNetwork() throws Exception {
List<TrafficDescriptor> tdList = new ArrayList<>();
tdList.add(new TrafficDescriptor.Builder()
.setOsAppId(new OsAppId(OsAppId.ANDROID_OS_ID, "ENTERPRISE", 1).getBytes())
.build());
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager,
createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE, tdList));
doReturn(mEnterpriseDataProfile).when(mDataProfileManager)
.getDataProfileForNetworkRequest(any(TelephonyNetworkRequest.class), anyInt());
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE);
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly(
InetAddresses.parseNumericAddress(IPV4_ADDRESS),
InetAddresses.parseNumericAddress(IPV6_ADDRESS));
}
@Test
public void testDataNetworkControllerCallback() throws Exception {
mDataNetworkControllerUT.registerDataNetworkControllerCallback(
mMockedDataNetworkControllerCallback);
processAllMessages();
testSetupDataNetwork();
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(true));
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any());
mDataNetworkControllerUT.unregisterDataNetworkControllerCallback(
mMockedDataNetworkControllerCallback);
processAllMessages();
}
@Test
public void testSimRemovalDataTearDown() throws Exception {
testSetupDataNetwork();
mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
processAllMessages();
verifyAllDataDisconnected();
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkDisconnected();
}
@Test
public void testSimRemovalAndThenInserted() throws Exception {
testSimRemovalDataTearDown();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// Insert the SIM again.
mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
TelephonyManager.SIM_STATE_LOADED, 0).sendToTarget();
processAllMessages();
verifyInternetConnected();
}
@Test
public void testDuplicateInterface() throws Exception {
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// The fota network request would result in duplicate interface.
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_FOTA));
processAllFutureMessages();
// There should be only one network.
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
assertThat(dataNetworkList.get(0).getDataProfile()).isEqualTo(mGeneralPurposeDataProfile);
verifyInternetConnected();
// Fota should not be connected.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
// There should be exactly 2 setup data call requests.
verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testMovingFromNoServiceToInService() throws Exception {
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Network becomes in-service.
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
verifyInternetConnected();
}
@Test
public void testMovingFromInServiceToNoService() throws Exception {
testSetupDataNetwork();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
// Verify we don't tear down the data network.
verifyInternetConnected();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UNKNOWN,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
// Verify we don't tear down the data network.
verifyInternetConnected();
}
@Test
public void testPsRestrictedAndLifted() throws Exception {
testSetupDataNetwork();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// PS restricted, existing PDN should stay.
mDataNetworkControllerUT.obtainMessage(6/*EVENT_PS_RESTRICT_ENABLED*/).sendToTarget();
processAllMessages();
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// PS restricted, new setup NOT allowed
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
setSuccessfulSetupDataResponse(mMockedDataServiceManagers
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// PS unrestricted, new setup is allowed
mDataNetworkControllerUT.obtainMessage(7/*EVENT_PS_RESTRICT_DISABLED*/).sendToTarget();
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@Test
public void testRatChanges() throws Exception {
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
testSetupDataNetwork();
// Now RAT changes from LTE to UMTS, make sure the network is lingered.
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UMTS,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
verifyInternetConnected();
// Now RAT changes from UMTS to GSM
doReturn(null).when(mDataProfileManager).getDataProfileForNetworkRequest(
any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_GSM));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_GSM,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
verifyAllDataDisconnected();
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkDisconnected();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// Now RAT changes from GSM to UMTS
doReturn(null).when(mDataProfileManager).getDataProfileForNetworkRequest(
any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_UMTS));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UMTS,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
doReturn(mGeneralPurposeDataProfile).when(mDataProfileManager)
.getDataProfileForNetworkRequest(any(TelephonyNetworkRequest.class), anyInt());
// Now RAT changes from UMTS to LTE
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
verifyInternetConnected();
}
@Test
public void testRatChangesLingeringNotSet() throws Exception {
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
TelephonyNetworkRequest fotaRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_FOTA);
mDataNetworkControllerUT.addNetworkRequest(fotaRequest);
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_FOTA);
// Now RAT changes from LTE to UMTS, since FOTA APN does not have lingering set, only
// network type bitmask should be used. Fota network should be torn down.
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UMTS,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
verifyAllDataDisconnected();
}
@Test
public void testVoiceCallEndedOnVoiceDataNonConcurrentNetwork() throws Exception {
doReturn(false).when(mSST).isConcurrentVoiceAndDataAllowed();
doReturn(PhoneConstants.State.OFFHOOK).when(mCT).getState();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Data should not be allowed when voice/data concurrent is not supported.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Call ended.
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
processAllMessages();
// It should have no internet setup at the beginning.
verifyAllDataDisconnected();
// But after some delays data should be restored.
moveTimeForward(500);
processAllMessages();
verifyInternetConnected();
}
@Test
public void testEcbmChanged() throws Exception {
doReturn(true).when(mPhone).isInCdmaEcm();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Data should not be allowed when the device is in ECBM.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Exit ECBM
doReturn(false).when(mPhone).isInCdmaEcm();
mDataNetworkControllerUT.obtainMessage(20/*EVENT_EMERGENCY_CALL_CHANGED*/).sendToTarget();
processAllMessages();
// Verify data is restored.
verifyInternetConnected();
}
@Test
public void testRoamingDataChanged() throws Exception {
doReturn(true).when(mServiceState).getDataRoaming();
// Roaming data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
processAllMessages();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Data should not be allowed when roaming data is disabled.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// Roaming data enabled
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
processAllMessages();
// Verify data is restored.
verifyInternetConnected();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// Roaming data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
processAllMessages();
// Verify data is torn down.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@Test
public void testDataEnabledChanged() throws Exception {
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Data should not be allowed when user data is disabled.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// User data enabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, true, mContext.getOpPackageName());
processAllMessages();
// Verify data is restored.
verifyInternetConnected();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// User data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
// Verify data is torn down.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@Test
public void testNotifyWhenSetDataEnabled() throws Exception {
// Set a valid sub id, DEFAULT_SUBSCRIPTION_ID
int subId = Integer.MAX_VALUE;
Field field = DataSettingsManager.class.getDeclaredField("mSubId");
field.setAccessible(true);
field.setInt(mDataNetworkControllerUT.getDataSettingsManager(), subId);
boolean isDataEnabled = mDataNetworkControllerUT.getDataSettingsManager().isDataEnabled();
doReturn(mDataNetworkControllerUT.getDataSettingsManager())
.when(mPhone).getDataSettingsManager();
MultiSimSettingController instance = MultiSimSettingController.getInstance();
MultiSimSettingController controller = Mockito.spy(
new MultiSimSettingController(mContext, mSubscriptionController));
doReturn(true).when(controller).isCarrierConfigLoadedForAllSub();
replaceInstance(MultiSimSettingController.class, "sInstance", null, controller);
controller.notifyAllSubscriptionLoaded();
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, !isDataEnabled,
mContext.getOpPackageName());
processAllMessages();
// Verify not to notify MultiSimSettingController
verify(controller, never()).notifyUserDataEnabled(anyInt(), anyBoolean());
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, isDataEnabled,
mContext.getOpPackageName());
processAllMessages();
// Verify not to notify MultiSimSettingController
verify(controller, never()).notifyUserDataEnabled(anyInt(), anyBoolean());
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, !isDataEnabled, "com.android.settings");
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, isDataEnabled, "com.android.settings");
processAllMessages();
// Verify to notify MultiSimSettingController exactly 2 times
verify(controller, times(2)).notifyUserDataEnabled(anyInt(), anyBoolean());
}
@Test
public void testMmsAlwaysAllowedDataDisabled() throws Exception {
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
// Always allow MMS
mDataNetworkControllerUT.getDataSettingsManager().setAlwaysAllowMmsData(true);
processAllMessages();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
// Make sure MMS is the only capability advertised, but not internet or SUPL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
// Remove MMS data enabled override
mDataNetworkControllerUT.getDataSettingsManager().setAlwaysAllowMmsData(false);
processAllMessages();
// Make sure MMS is torn down when the override is disabled.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
}
@Test
public void testMmsAlwaysAllowedRoamingDisabled() throws Exception {
// Data roaming disabled
doReturn(true).when(mServiceState).getDataRoaming();
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
processAllMessages();
// Device is roaming
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
// Always allow MMS
mDataNetworkControllerUT.getDataSettingsManager().setAlwaysAllowMmsData(true);
processAllMessages();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
// Make sure MMS is not allowed. MMS always allowed should be only applicable to data
// disabled case.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
}
@Test
public void testUnmeteredRequestPreferredOnIwlan() throws Exception {
// Preferred on cellular
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(anyInt());
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Data should not be allowed when roaming + user data are disabled (soft failure reasons)
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Set transport to WLAN (unmetered)
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(
eq(NetworkCapabilities.NET_CAPABILITY_INTERNET));
// Data remain disabled, but trigger the preference evaluation.
mDataNetworkControllerUT.obtainMessage(21 /*EVENT_EVALUATE_PREFERRED_TRANSPORT*/,
NetworkCapabilities.NET_CAPABILITY_INTERNET, 0).sendToTarget();
mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
processAllMessages();
// Verify data is allowed even if data is disabled.
verifyInternetConnected();
}
@Test
public void testUnmeteredRequestDataRoamingDisabled() throws Exception {
// Data roaming disabled
doReturn(true).when(mServiceState).getDataRoaming();
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
processAllMessages();
// MMS is unmetered
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "dun", "supl"});
carrierConfigChanged();
// Manually set data roaming to false in case ro.com.android.dataroaming is true.
// TODO(b/232575718): Figure out a way to mock ro.com.android.dataroaming for tests.
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
// Device is roaming
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@Test
public void testUnmeteredRequestDataDisabled() throws Exception {
// MMS is unmetered
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "dun", "supl"});
carrierConfigChanged();
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@Test
public void testEmergencyRequest() throws Exception {
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_EIMS));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_EIMS);
verifyConnectedNetworkHasDataProfile(mEmergencyDataProfile);
}
@Test
public void testHandoverRuleFromString() {
HandoverRule handoverRule = new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, "
+ "target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed");
assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.GERAN,
AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN, AccessNetworkType.NGRAN,
AccessNetworkType.IWLAN);
assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.GERAN,
AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN, AccessNetworkType.NGRAN,
AccessNetworkType.IWLAN);
assertThat(handoverRule.type).isEqualTo(HandoverRule.RULE_TYPE_ALLOWED);
assertThat(handoverRule.isOnlyForRoaming).isFalse();
assertThat(handoverRule.networkCapabilities).isEmpty();
handoverRule = new HandoverRule("source= NGRAN| IWLAN, "
+ "target = EUTRAN, type = disallowed ");
assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.NGRAN,
AccessNetworkType.IWLAN);
assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.EUTRAN);
assertThat(handoverRule.type).isEqualTo(HandoverRule.RULE_TYPE_DISALLOWED);
assertThat(handoverRule.isOnlyForRoaming).isFalse();
assertThat(handoverRule.networkCapabilities).isEmpty();
handoverRule = new HandoverRule("source= IWLAN, "
+ "target = EUTRAN, type = disallowed, roaming = true,"
+ " capabilities = IMS | EIMS ");
assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.IWLAN);
assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.EUTRAN);
assertThat(handoverRule.type).isEqualTo(HandoverRule.RULE_TYPE_DISALLOWED);
assertThat(handoverRule.networkCapabilities).containsExactly(
NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_EIMS);
assertThat(handoverRule.isOnlyForRoaming).isTrue();
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("V2hhdCBUaGUgRnVjayBpcyB0aGlzIQ=="));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN, target=IWLAN, type=wtf"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN, target=NGRAN, type=allowed"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=IWLAN, target=WTFRAN, type=allowed"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=IWLAN, target=|, type=allowed"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities=|"));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities="));
assertThrows(IllegalArgumentException.class,
() -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, "
+ "capabilities=wtf"));
}
@Test
public void testIsNetworkTypeCongested() throws Exception {
Set<Integer> congestedNetworkTypes = new ArraySet<>();
doReturn(congestedNetworkTypes).when(mDataNetworkController)
.getCongestedOverrideNetworkTypes();
testSetupDataNetwork();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Set 5G unmetered
congestedNetworkTypes.add(TelephonyManager.NETWORK_TYPE_NR);
mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED,
new int[]{TelephonyManager.NETWORK_TYPE_NR}).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertEquals(congestedNetworkTypes,
mDataNetworkControllerUT.getCongestedOverrideNetworkTypes());
assertTrue(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED));
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
assertFalse(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED));
// Set all network types metered
congestedNetworkTypes.clear();
mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED, 0,
TelephonyManager.getAllNetworkTypes()).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertTrue(mDataNetworkControllerUT.getCongestedOverrideNetworkTypes().isEmpty());
assertTrue(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED));
}
@Test
public void testIsNetworkTypeUnmeteredViaSubscriptionOverride() throws Exception {
Set<Integer> unmeteredNetworkTypes = new ArraySet<>();
doReturn(unmeteredNetworkTypes).when(mDataNetworkController)
.getUnmeteredOverrideNetworkTypes();
testSetupDataNetwork();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Set 5G unmetered
unmeteredNetworkTypes.add(TelephonyManager.NETWORK_TYPE_NR);
mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED,
new int[]{TelephonyManager.NETWORK_TYPE_NR}).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertEquals(unmeteredNetworkTypes,
mDataNetworkControllerUT.getUnmeteredOverrideNetworkTypes());
assertFalse(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isFalse();
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
assertTrue(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isTrue();
// Set all network types metered
unmeteredNetworkTypes.clear();
mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED, 0,
TelephonyManager.getAllNetworkTypes()).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertTrue(mDataNetworkControllerUT.getUnmeteredOverrideNetworkTypes().isEmpty());
assertFalse(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isFalse();
}
@Test
public void testIsNetworkTypeUnmeteredViaSubscriptionPlans() throws Exception {
List<SubscriptionPlan> subscriptionPlans = new ArrayList<>();
doReturn(subscriptionPlans).when(mDataNetworkController).getSubscriptionPlans();
testSetupDataNetwork();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Set 5G unmetered
SubscriptionPlan unmetered5GPlan = SubscriptionPlan.Builder
.createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
Period.ofMonths(1))
.setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
.setNetworkTypes(new int[]{TelephonyManager.NETWORK_TYPE_NR})
.build();
SubscriptionPlan generalMeteredPlan = SubscriptionPlan.Builder
.createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
Period.ofMonths(1))
.setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
.setDataUsage(500_000_000, System.currentTimeMillis())
.build();
subscriptionPlans.add(generalMeteredPlan);
subscriptionPlans.add(unmetered5GPlan);
mDataNetworkControllerUT.obtainMessage(22/*EVENT_SUBSCRIPTION_PLANS_CHANGED*/,
new SubscriptionPlan[]{generalMeteredPlan, unmetered5GPlan}).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertEquals(subscriptionPlans, mDataNetworkControllerUT.getSubscriptionPlans());
assertFalse(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isFalse();
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
assertTrue(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isTrue();
// Set all network types metered
subscriptionPlans.clear();
mDataNetworkControllerUT.obtainMessage(22/*EVENT_SUBSCRIPTION_PLANS_CHANGED*/,
new SubscriptionPlan[]{}).sendToTarget();
dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
processAllMessages();
assertTrue(mDataNetworkControllerUT.getSubscriptionPlans().isEmpty());
assertFalse(dataNetwork.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
assertThat(mDataNetworkControllerUT.isInternetUnmetered()).isFalse();
}
@Test
public void testOnSinglePdnArbitrationExemptIms() throws Exception {
// On CDMA network, only one data network is allowed.
serviceStateChanged(TelephonyManager.NETWORK_TYPE_1xRTT,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
// Preferred on cellular
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(anyInt());
// Add IMS
TelephonyNetworkRequest ims = createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
mDataNetworkControllerUT.addNetworkRequest(ims);
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Add internet, should be compatible with
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
setSuccessfulSetupDataResponse(mMockedDataServiceManagers
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Add MMS, whose priority > internet, internet should be town down, IMS left untouched
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
setSuccessfulSetupDataResponse(mMockedDataServiceManagers
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 3);
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Temporarily remove IMS
mDataNetworkControllerUT.removeNetworkRequest(ims);
processAllMessages();
List<DataNetwork> dataNetworks = getDataNetworks();
dataNetworks.get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED);
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
// Add IMS, should be compatible with the existing internet
setSuccessfulSetupDataResponse(mMockedDataServiceManagers
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 4);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testLinkStatusChanged() throws Exception {
testSetupDataNetwork();
verify(mMockedDataNetworkControllerCallback).onPhysicalLinkStatusChanged(
eq(DataCallResponse.LINK_STATUS_ACTIVE));
DataNetwork dataNetwork = getDataNetworks().get(0);
DataCallResponse response = createDataCallResponse(1, DataCallResponse.LINK_STATUS_DORMANT);
dataNetwork.obtainMessage(8 /*EVENT_DATA_STATE_CHANGED */,
new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
List.of(response), null)).sendToTarget();
processAllMessages();
verify(mMockedDataNetworkControllerCallback).onPhysicalLinkStatusChanged(
eq(DataCallResponse.LINK_STATUS_DORMANT));
assertThat(mDataNetworkControllerUT.getDataActivity()).isEqualTo(
TelephonyManager.DATA_ACTIVITY_DORMANT);
}
@Test
public void testHandoverDataNetwork() throws Exception {
testSetupImsDataNetwork();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Before handover the data profile is the cellular IMS data profile
verifyConnectedNetworkHasDataProfile(mImsCellularDataProfile);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// Verify that IWLAN handover succeeded.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// After handover the data profile is the IWLAN IMS data profile
verifyConnectedNetworkHasDataProfile(mImsIwlanDataProfile);
}
@Test
public void testHandoverDataNetworkBackToBackPreferenceChanged() throws Exception {
testSetupImsDataNetwork();
Mockito.reset(mMockedWlanDataServiceManager);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// Capture the message for setup data call response. We want to delay it.
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mMockedWlanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
messageCaptor.capture());
// Before setup data call response, change the preference back to cellular.
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Before setup data call response, change the preference back to IWLAN.
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// Finally handover is completed.
Message msg = messageCaptor.getValue();
DataCallResponse response = new DataCallResponse.Builder()
.setCause(DataFailCause.NONE)
.build();
msg.getData().putParcelable("data_call_response", response);
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.sendToTarget();
processAllMessages();
// Make sure handover request is only sent once.
verify(mMockedWlanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), messageCaptor.capture());
}
@Test
public void testHandoverDataNetworkNotAllowedByPolicy() throws Exception {
mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
new String[]{"source=EUTRAN, target=IWLAN, type=disallowed, capabilities=MMS|IMS",
"source=IWLAN, target=EUTRAN, type=disallowed, capabilities=MMS"});
// Force data config manager to reload the carrier config.
mDataNetworkControllerUT.getDataConfigManager().obtainMessage(
1/*EVENT_CARRIER_CONFIG_CHANGED*/).sendToTarget();
processAllMessages();
testSetupImsDataNetwork();
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// After this, IMS data network should be disconnected, and DNC should attempt to
// establish a new one on IWLAN
// Verify all data disconnected.
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
// A new data network should be connected on IWLAN
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
assertThat(dataNetworkList.get(0).isConnected()).isTrue();
assertThat(dataNetworkList.get(0).getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
assertThat(dataNetworkList.get(0).getTransport())
.isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// test IWLAN -> EUTRAN no need to tear down because the disallowed rule only applies to MMS
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.obtainMessage(21/*EVENT_PREFERRED_TRANSPORT_CHANGED*/,
NetworkCapabilities.NET_CAPABILITY_IMS, 0).sendToTarget();
Mockito.clearInvocations(mMockedWwanDataServiceManager);
processAllMessages();
// Verify that IWWAN handover succeeded.
assertThat(getDataNetworks().get(0).getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(
anyInt(), any(), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_HANDOVER), any(), anyInt(), any(), any(), eq(true),
any());
}
@Test
public void testHandoverDataNetworkNotAllowedByRoamingPolicy() throws Exception {
mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
new String[]{"source=EUTRAN|NGRAN|IWLAN, target=EUTRAN|NGRAN|IWLAN, roaming=true, "
+ "type=disallowed, capabilities=IMS"});
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
// Force data config manager to reload the carrier config.
mDataNetworkControllerUT.getDataConfigManager().obtainMessage(
1/*EVENT_CARRIER_CONFIG_CHANGED*/).sendToTarget();
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
processAllMessages();
// Bring up IMS PDN on IWLAN
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mImsIwlanDataProfile);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Verify IMS PDN is connected.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// After this, IMS data network should be disconnected, and DNC should attempt to
// establish a new one on cellular
processAllMessages();
// Verify all data disconnected.
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
// Should setup a new one instead of handover.
verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
anyBoolean(), anyBoolean(), eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
// A new data network should be connected on IWLAN
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
assertThat(dataNetworkList.get(0).isConnected()).isTrue();
assertThat(dataNetworkList.get(0).getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
assertThat(dataNetworkList.get(0).getTransport())
.isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
}
@Test
public void testHandoverDataNetworkRetry() throws Exception {
testSetupImsDataNetwork();
setFailedSetupDataResponse(mMockedWlanDataServiceManager,
DataFailCause.HANDOVER_FAILED, -1, true);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
DataNetwork dataNetwork = getDataNetworks().get(0);
// Verify that data network is still on cellular
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 1);
processAllFutureMessages();
dataNetwork = getDataNetworks().get(0);
// Verify that data network is handovered to IWLAN
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
}
@Test
public void testHandoverDataNetworkRetryReachedMaximum() throws Exception {
testSetupImsDataNetwork();
setFailedSetupDataResponse(mMockedWlanDataServiceManager,
DataFailCause.HANDOVER_FAILED, -1, true);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
processAllFutureMessages();
// Should retried 5 times, which is the maximum based on the retry config rules.
verify(mMockedWlanDataServiceManager, times(6)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_HANDOVER), any(), anyInt(), any(), any(),
anyBoolean(), any(Message.class));
DataNetwork dataNetwork = getDataNetworks().get(0);
// Verify that data network is finally setup on IWLAN.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
verify(mMockedWlanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
anyBoolean(), anyBoolean(), eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testHandoverDataNetworkRetryReachedMaximumNetworkRequestRemoved() throws Exception {
TelephonyNetworkRequest networkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
processAllMessages();
setFailedSetupDataResponse(mMockedWlanDataServiceManager,
DataFailCause.HANDOVER_FAILED, -1, true);
mDataNetworkControllerUT.removeNetworkRequest(networkRequest);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
processAllMessages();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Verify that data network should remain on cellular.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// There shouldn't be any attempt to retry handover on IWLAN.
verify(mMockedWlanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_HANDOVER), any(), anyInt(), any(), any(),
anyBoolean(), any(Message.class));
// There shouldn't be any attempt to bring up a new one on IWLAN as well.
verify(mMockedWlanDataServiceManager, never()).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(),
anyBoolean(), any(Message.class));
}
@Test
public void testHandoverDataNetworkRetryReachedMaximumDelayImsTearDown() throws Exception {
// Voice call is ongoing
doReturn(PhoneConstants.State.OFFHOOK).when(mCT).getState();
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
true);
carrierConfigChanged();
testSetupImsDataNetwork();
setFailedSetupDataResponse(mMockedWlanDataServiceManager,
DataFailCause.HANDOVER_FAILED, -1, true);
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
processAllFutureMessages();
// Should retried 5 times, which is the maximum based on the retry config rules.
verify(mMockedWlanDataServiceManager, times(6)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_HANDOVER), any(), anyInt(), any(), any(),
anyBoolean(), any(Message.class));
DataNetwork dataNetwork = getDataNetworks().get(0);
// Verify that data network is still on WWAN because voice call is still ongoing.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
}
// Test the device enters from 4G to 3G, and QNS switches the pref just before that happens.
// Make sure we don't tear down the network and let it handover to IWLAN successfully.
@Test
public void testHandoverDataNetworkWhileSwitchTo3G() throws Exception {
testSetupImsDataNetwork();
// Before handover the data profile is the cellular IMS data profile
verifyConnectedNetworkHasDataProfile(mImsCellularDataProfile);
// Long delay handover
setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 1, 3000);
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
mAccessNetworksManagerCallback.onPreferredTransportChanged(
NetworkCapabilities.NET_CAPABILITY_IMS);
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UMTS,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
processAllMessages();
// Move the time a little bit, handover still not responded.
moveTimeForward(500);
processAllMessages();
DataNetwork dataNetwork = getDataNetworks().get(0);
// Verify the network is still on cellular, waiting for handover, although already on 3G.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Now handover should complete.
moveTimeForward(5000);
processAllMessages();
dataNetwork = getDataNetworks().get(0);
// Verify that IWLAN handover succeeded.
assertThat(dataNetwork.getTransport()).isEqualTo(
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// After handover the data profile is the IWLAN IMS data profile
verifyConnectedNetworkHasDataProfile(mImsIwlanDataProfile);
}
@Test
public void testSetupDataNetworkRetrySuggestedByNetwork() {
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllFutureMessages();
// Should retried 20 times, which is the maximum based on the retry config rules.
verify(mMockedWwanDataServiceManager, times(21)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testSetupDataNetworkRetryFailed() {
mDataNetworkControllerUT.getDataRetryManager()
.registerCallback(mMockedDataRetryManagerCallback);
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
// Process first retry
moveTimeForward(2500);
processAllMessages();
verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
ArgumentCaptor<DataRetryManager.DataSetupRetryEntry> retryEntry =
ArgumentCaptor.forClass(DataRetryManager.DataSetupRetryEntry.class);
verify(mMockedDataRetryManagerCallback, times(1))
.onDataNetworkSetupRetry(retryEntry.capture());
assertThat(retryEntry.getValue().getState()).isEqualTo(
DataRetryManager.DataRetryEntry.RETRY_STATE_FAILED);
// Cause data network setup failed due to RADIO_DISABLED_BY_CARRIER
doReturn(false).when(mSST).getPowerStateFromCarrier();
// Process second retry and ensure data network setup failed
moveTimeForward(3000);
processAllMessages();
verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
verify(mMockedDataRetryManagerCallback, times(2))
.onDataNetworkSetupRetry(retryEntry.capture());
assertThat(retryEntry.getValue().getState()).isEqualTo(
DataRetryManager.DataRetryEntry.RETRY_STATE_FAILED);
// Data network setup allowed again
doReturn(true).when(mSST).getPowerStateFromCarrier();
// Should not retry again after retry failure
processAllFutureMessages();
verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testSetupDataNetworkRetryFailedNetworkRequestRemoved() {
mDataNetworkControllerUT.getDataRetryManager()
.registerCallback(mMockedDataRetryManagerCallback);
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
TelephonyNetworkRequest tnr = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_INTERNET);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
Mockito.clearInvocations(mMockedWwanDataServiceManager);
logd("Remove internet network request");
mDataNetworkControllerUT.removeNetworkRequest(tnr);
moveTimeForward(2500);
processAllMessages();
// There should be no retry since request has been removed.
verify(mMockedWwanDataServiceManager, never()).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
Mockito.clearInvocations(mMockedWwanDataServiceManager);
// Now send another IMS request
tnr = createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
Mockito.clearInvocations(mMockedWwanDataServiceManager);
logd("Remove IMS network request");
mDataNetworkControllerUT.removeNetworkRequest(tnr);
// There should be no retry since request has been removed.
verify(mMockedWwanDataServiceManager, never()).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testSetupDataNetworkPermanentFailure() {
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.PROTOCOL_ERRORS,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllFutureMessages();
// There should be only one attempt, and no retry should happen because it's a permanent
// failure.
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testSetupDataNetworkNetworkSuggestedNeverRetry() {
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.PROTOCOL_ERRORS,
Long.MAX_VALUE, false);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllFutureMessages();
// There should be only one attempt, and no retry should happen because it's a permanent
// failure.
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testSetupDataNetworkNetworkSuggestedRetryTimerDataThrottled() {
mDataNetworkControllerUT.getDataRetryManager()
.registerCallback(mMockedDataRetryManagerCallback);
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.PROTOCOL_ERRORS,
10000, false);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
// There should be only one attempt, and no retry should happen because the second one
// was throttled.
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor =
ArgumentCaptor.forClass(List.class);
verify(mMockedDataRetryManagerCallback)
.onThrottleStatusChanged(throttleStatusCaptor.capture());
assertThat(throttleStatusCaptor.getValue()).hasSize(1);
ThrottleStatus throttleStatus = throttleStatusCaptor.getValue().get(0);
assertThat(throttleStatus.getApnType()).isEqualTo(ApnSetting.TYPE_IMS);
assertThat(throttleStatus.getRetryType())
.isEqualTo(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION);
assertThat(throttleStatus.getTransportType())
.isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
}
@Test
public void testTacChangesClearThrottlingAndRetryHappens() throws Exception {
testSetupDataNetworkNetworkSuggestedRetryTimerDataThrottled();
processAllFutureMessages();
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 1);
logd("Sending TAC_CHANGED event");
mDataNetworkControllerUT.obtainMessage(25/*EVENT_TAC_CHANGED*/).sendToTarget();
mDataNetworkControllerUT.getDataRetryManager().obtainMessage(10/*EVENT_TAC_CHANGED*/)
.sendToTarget();
processAllFutureMessages();
// TAC changes should clear the already-scheduled retry and throttling.
assertThat(mDataNetworkControllerUT.getDataRetryManager().isAnySetupRetryScheduled(
mImsCellularDataProfile, AccessNetworkConstants.TRANSPORT_TYPE_WWAN)).isFalse();
// But DNC should re-evaluate unsatisfied request and setup IMS again.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testNrAdvancedByPco() throws Exception {
testSetupDataNetwork();
verify(mMockedDataNetworkControllerCallback, never())
.onNrAdvancedCapableByPcoChanged(anyBoolean());
mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1});
processAllMessages();
verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{0});
processAllMessages();
verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false));
}
@Test
public void testNrAdvancedByEarlyPco() {
Mockito.reset(mMockedWwanDataServiceManager);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// PCO data arrives before data network entering connected state.
mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1});
processAllMessages();
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
messageCaptor.capture());
// Send setup data call complete message.
Message msg = messageCaptor.getValue();
msg.getData().putParcelable("data_call_response",
createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE));
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.sendToTarget();
processAllMessages();
verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
}
@Test
public void testNrAdvancedByPcoMultipleNetworks() throws Exception {
testSetupDataNetwork();
setSuccessfulSetupDataResponse(mMockedDataServiceManagers
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
testSetupImsDataNetwork();
verify(mMockedDataNetworkControllerCallback, never())
.onNrAdvancedCapableByPcoChanged(anyBoolean());
mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1});
processAllMessages();
verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
}
@Test
public void testNrAdvancedByEarlyUnrelatedPco() {
Mockito.reset(mMockedWwanDataServiceManager);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// Unrelated PCO data arrives before data network entering connected state.
mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1});
processAllMessages();
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
messageCaptor.capture());
// Send setup data call complete message.
Message msg = messageCaptor.getValue();
msg.getData().putParcelable("data_call_response",
createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE));
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.sendToTarget();
processAllMessages();
verify(mMockedDataNetworkControllerCallback, never()).onNrAdvancedCapableByPcoChanged(
anyBoolean());
}
@Test
public void testSetupDataNetworkVcnManaged() throws Exception {
// VCN managed
setVcnManagerPolicy(true, false);
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build();
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
// VCN managed network won't trigger onInternetDataNetworkConnected.
// DataNetwork.isInternetSupported() is false for VCN managed network.
verify(mMockedDataNetworkControllerCallback, never())
.onInternetDataNetworkConnected(any());
List<DataNetwork> dataNetworks = getDataNetworks();
assertThat(dataNetworks).hasSize(1);
assertThat(dataNetworks.get(0).getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)).isFalse();
assertThat(dataNetworks.get(0).isInternetSupported()).isFalse();
assertThat(dataNetworks.get(0).getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
}
@Test
public void testSetupDataNetworkVcnRequestedTeardown() throws Exception {
// VCN managed, tear down on setup.
setVcnManagerPolicy(true, true);
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build();
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
// Should not be any data network created.
List<DataNetwork> dataNetworks = getDataNetworks();
assertThat(dataNetworks).hasSize(0);
}
@Test
public void testVcnManagedNetworkPolicyChanged() throws Exception {
testSetupDataNetworkVcnManaged();
setVcnManagerPolicy(true, true);
ArgumentCaptor<VcnNetworkPolicyChangeListener> listenerCaptor =
ArgumentCaptor.forClass(VcnNetworkPolicyChangeListener.class);
verify(mVcnManager).addVcnNetworkPolicyChangeListener(any(Executor.class),
listenerCaptor.capture());
// Trigger policy changed event
VcnNetworkPolicyChangeListener listener = listenerCaptor.getValue();
listener.onPolicyChanged();
processAllMessages();
List<DataNetwork> dataNetworks = getDataNetworks();
assertThat(dataNetworks).hasSize(0);
}
@Test
public void testDataDisableNotTearingDownUnmetered() throws Exception {
// User data enabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, true, mContext.getOpPackageName());
processAllMessages();
testSetupImsDataNetwork();
Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
// User data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
// There shouldn't be all data disconnected event.
verify(mMockedDataNetworkControllerCallback, never())
.onAnyDataNetworkExistingChanged(anyBoolean());
// Verify IMS is still alive.
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
assertThat(dataNetworkList.get(0).getNetworkCapabilities()
.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
assertThat(dataNetworkList.get(0).isConnected()).isTrue();
}
@Test
public void testNonVoPSNoIMSSetup() throws Exception {
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
verifyAllDataDisconnected();
}
@Test
public void testNonVoPStoVoPSImsSetup() throws Exception {
// VOPS not supported
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
// VoPS supported
dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testDelayImsTearDownCsRequestsToTearDown() throws Exception {
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
true);
TelephonyNetworkRequest networkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
processAllMessages();
// Call is ongoing
doReturn(PhoneConstants.State.OFFHOOK).when(mCT).getState();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
verifyConnectedNetworkHasDataProfile(mImsCellularDataProfile);
List<DataNetwork> dataNetworks = getDataNetworks();
assertThat(dataNetworks).hasSize(1);
dataNetworks.get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_RAT_NOT_ALLOWED);
processAllMessages();
// Make sure IMS network is still connected.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
verifyConnectedNetworkHasDataProfile(mImsCellularDataProfile);
// Now connectivity service requests to tear down the data network.
mDataNetworkControllerUT.removeNetworkRequest(networkRequest);
dataNetworks.get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED);
processAllMessages();
// All data (including IMS) should be torn down.
verifyAllDataDisconnected();
}
@Test
public void testUnmeteredMmsWhenDataDisabled() throws Exception {
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "dun", "supl"});
carrierConfigChanged();
// User data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
// Make sure MMS is the only capability advertised, but not internet or SUPL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
}
@Test
public void testUnmeteredMmsWhenRoamingDisabled() throws Exception {
mCarrierConfig.putStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "dun", "supl"});
carrierConfigChanged();
// Roaming data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
processAllMessages();
// Device is roaming
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
processAllMessages();
// Make sure MMS is the only capability advertised, but not internet or SUPL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
}
@Test
public void testRestrictedNetworkRequestDataDisabled() throws Exception {
// User data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
// Create a restricted network request.
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET,
NetworkCapabilities.NET_CAPABILITY_SUPL, NetworkCapabilities.NET_CAPABILITY_MMS);
List<DataNetwork> dataNetworks = getDataNetworks();
// Make sure the network is restricted.
assertThat(dataNetworks.get(0).getNetworkCapabilities()
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isFalse();
}
@Test
public void testRestrictedNetworkRequestDataEnabled() throws Exception {
// Create a restricted network request.
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET,
NetworkCapabilities.NET_CAPABILITY_SUPL, NetworkCapabilities.NET_CAPABILITY_MMS,
// Because data is enabled, even though the network request is restricted, the
// network should still be not-restricted.
NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
}
@Test
public void testSinglePdnArbitration() throws Exception {
// On old 1x network, only one data network is allowed.
serviceStateChanged(TelephonyManager.NETWORK_TYPE_1xRTT,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_DUN));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllFutureMessages();
// Lower priority network should not trump the higher priority network.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
// Now send a higher priority network request
TelephonyNetworkRequest fotaRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_FOTA);
mDataNetworkControllerUT.addNetworkRequest(fotaRequest);
processAllFutureMessages();
// The existing internet data network should be torn down.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
// The higher priority emergency data network should be established.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_FOTA);
// Now remove the fota request and tear down fota network.
mDataNetworkControllerUT.removeNetworkRequest(fotaRequest);
processAllMessages();
List<DataNetwork> dataNetworks = getDataNetworks();
dataNetworks.get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED);
processAllMessages();
// The tethering data network should come back since now it has the highest priority after
// fota is gone.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
}
@Test
public void testImsGracefulTearDown() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
nativeNetworkRequest, mPhone);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
processAllMessages();
Mockito.clearInvocations(mPhone);
// SIM removal
mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
processAllMessages();
// Make sure data network enters disconnecting state
ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
ArgumentCaptor.forClass(PreciseDataConnectionState.class);
verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
PreciseDataConnectionState pdcs = pdcsCaptor.getValue();
assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING);
// IMS de-registered. Now data network is safe to be torn down.
Mockito.clearInvocations(mPhone);
setImsRegistered(false);
setRcsRegistered(false);
processAllMessages();
// All data should be disconnected.
verifyAllDataDisconnected();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
pdcs = pdcsCaptor.getValue();
assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
}
@Test
public void testNetworkRequestRemovedBeforeRetry() {
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
TelephonyNetworkRequest networkRequest = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_INTERNET);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
logd("Removing network request.");
mDataNetworkControllerUT.removeNetworkRequest(networkRequest);
processAllMessages();
// There should be only one invocation, which is the original setup data request. There
// shouldn't be more than 1 (i.e. should not retry).
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
}
@Test
public void testGetInternetDataDisallowedReasons() {
List<DataDisallowedReason> reasons = mDataNetworkControllerUT
.getInternetDataDisallowedReasons();
assertThat(reasons).isEmpty();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_UNKNOWN,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
reasons = mDataNetworkControllerUT.getInternetDataDisallowedReasons();
assertThat(reasons).containsExactly(DataDisallowedReason.NOT_IN_SERVICE,
DataDisallowedReason.NO_SUITABLE_DATA_PROFILE);
}
@Test
public void testEmergencySuplDataDisabled() throws Exception {
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
doReturn(true).when(mPhone).isInEmergencyCall();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_SUPL));
processAllMessages();
// Make sure SUPL is the only capability advertised, but not internet or MMS.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_SUPL);
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
}
@Test
public void testEmergencyCallDataDisabled() throws Exception {
doReturn(true).when(mPhone).isInEmergencyCall();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
verifyInternetConnected();
// Data disabled
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
processAllMessages();
// Make sure internet is not connected. (Previously it has a bug due to incorrect logic
// to determine it's for emergency SUPL).
verifyAllDataDisconnected();
}
@Test
public void testDataActivity() {
doReturn(TelephonyManager.DATA_ACTIVITY_IN).when(mLinkBandwidthEstimator).getDataActivity();
mLinkBandwidthEstimatorCallback.onDataActivityChanged(TelephonyManager.DATA_ACTIVITY_IN);
processAllMessages();
assertThat(mDataNetworkControllerUT.getDataActivity()).isEqualTo(
TelephonyManager.DATA_ACTIVITY_IN);
doReturn(TelephonyManager.DATA_ACTIVITY_OUT).when(mLinkBandwidthEstimator)
.getDataActivity();
mLinkBandwidthEstimatorCallback.onDataActivityChanged(TelephonyManager.DATA_ACTIVITY_OUT);
processAllMessages();
assertThat(mDataNetworkControllerUT.getDataActivity()).isEqualTo(
TelephonyManager.DATA_ACTIVITY_OUT);
doReturn(TelephonyManager.DATA_ACTIVITY_INOUT).when(mLinkBandwidthEstimator)
.getDataActivity();
mLinkBandwidthEstimatorCallback.onDataActivityChanged(TelephonyManager.DATA_ACTIVITY_INOUT);
processAllMessages();
assertThat(mDataNetworkControllerUT.getDataActivity()).isEqualTo(
TelephonyManager.DATA_ACTIVITY_INOUT);
doReturn(TelephonyManager.DATA_ACTIVITY_NONE).when(mLinkBandwidthEstimator)
.getDataActivity();
mLinkBandwidthEstimatorCallback.onDataActivityChanged(TelephonyManager.DATA_ACTIVITY_NONE);
processAllMessages();
assertThat(mDataNetworkControllerUT.getDataActivity()).isEqualTo(
TelephonyManager.DATA_ACTIVITY_NONE);
}
@Test
public void testHandoverDataNetworkOos() throws Exception {
ServiceState ss = new ServiceState();
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
testSetupImsDataNetwork();
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// Verify that handover is not performed.
verify(mMockedWlanDataServiceManager, never()).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(), anyBoolean(),
any(Message.class));
// IMS network should be torn down.
verifyAllDataDisconnected();
}
@Test
public void testHandoverDataNetworkNonVops() throws Exception {
ServiceState ss = new ServiceState();
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Change the preference to cellular
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Verify that handover is not performed.
verify(mMockedWwanDataServiceManager, never()).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
// IMS network should be torn down.
verifyAllDataDisconnected();
}
@Test
public void testNonMmtelImsHandoverDataNetworkNonVops() throws Exception {
ServiceState ss = new ServiceState();
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
// Bring up the IMS network that does not require MMTEL
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
// Even though the network request does not have MMTEL, but the network support it, so
// the network capabilities should still have MMTEL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Change the preference to cellular
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Verify that handover is performed
verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
// The IMS network should still have IMS and MMTEL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testMmtelImsDataNetworkMovingToNonVops() throws Exception {
ServiceState ss = new ServiceState();
// VoPS network
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
// Bring up the IMS network that does require MMTEL
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
// the network capabilities should have IMS and MMTEL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
ss = new ServiceState();
// Non VoPS network
dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
.build());
processServiceStateRegStateForTest(ss);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
processAllMessages();
// The IMS network should be torn down by data network controller.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testVoPStoNonVoPSDelayImsTearDown() throws Exception {
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
true);
carrierConfigChanged();
// VoPS supported
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS);
doReturn(PhoneConstants.State.OFFHOOK).when(mCT).getState();
dsri = new DataSpecificRegistrationInfo(8, false, true, true,
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
// Make sure IMS is still connected.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
// Call ends
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
processAllMessages();
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
}
@Test
public void testDeactivateDataOnOldHal() throws Exception {
doAnswer(invocation -> {
// Only send the deactivation data response, no data call list changed event.
Message msg = (Message) invocation.getArguments()[2];
msg.sendToTarget();
return null;
}).when(mMockedWwanDataServiceManager).deactivateDataCall(
anyInt(), anyInt(), any(Message.class));
// Simulate old devices
doReturn(RIL.RADIO_HAL_VERSION_1_6).when(mPhone).getHalVersion();
testSetupDataNetwork();
mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
processAllMessages();
verifyAllDataDisconnected();
verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkDisconnected();
}
@Test
public void testHandoverWhileSetupDataCallInProgress() throws Exception {
// Long delay setup failure
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false, 10000);
mDataNetworkControllerUT.addNetworkRequest(
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL));
processAllMessages();
// Change the preference to IWLAN while setup data is still ongoing.
updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
// Data should not be connected.
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
// There shouldn't be any attempt to bring up IMS on IWLAN even though the preference
// has already changed, because the previous setup is still ongoing.
verify(mMockedWlanDataServiceManager, never()).setupDataCall(eq(AccessNetworkType.IWLAN),
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
processAllFutureMessages();
// Should setup a new one instead of handover.
verify(mMockedWlanDataServiceManager).setupDataCall(eq(AccessNetworkType.IWLAN),
any(DataProfile.class), anyBoolean(), anyBoolean(),
eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(), anyBoolean(),
any(Message.class));
// IMS should be connected.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
public void testRemoveNetworkRequest() throws Exception {
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, 0, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
nativeNetworkRequest, mPhone));
processAllMessages();
// Intentionally create a new telephony request with the original native network request.
TelephonyNetworkRequest request = new TelephonyNetworkRequest(nativeNetworkRequest, mPhone);
mDataNetworkControllerUT.removeNetworkRequest(request);
processAllFutureMessages();
List<DataNetwork> dataNetworkList = getDataNetworks();
// The data network should not be torn down after network request removal.
assertThat(dataNetworkList).hasSize(1);
// But should be detached from the data network.
assertThat(dataNetworkList.get(0).getAttachedNetworkRequestList()).isEmpty();
assertThat(dataNetworkList.get(0).isConnected()).isTrue();
}
@Test
public void testTempDdsSwitchTearDown() throws Exception {
TelephonyNetworkRequest request = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_INTERNET);
mDataNetworkControllerUT.addNetworkRequest(request);
processAllMessages();
// Now DDS temporarily switched to phone 1
doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
// Simulate telephony network factory remove request due to switch.
mDataNetworkControllerUT.removeNetworkRequest(request);
processAllMessages();
// Data should be torn down on this non-preferred sub.
verifyAllDataDisconnected();
}
@Test
public void testSetupDataOnNonDds() throws Exception {
// Now DDS switched to phone 1
doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
TelephonyNetworkRequest request = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_MMS);
// Test Don't allow setup if both data and voice OOS
serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_1XRTT,
// data, voice, Iwlan reg state
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null);
mDataNetworkControllerUT.addNetworkRequest(request);
processAllMessages();
verifyAllDataDisconnected();
// Test Don't allow setup if CS is in service, but current RAT is already PS(e.g. LTE)
serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null);
verifyAllDataDisconnected();
// Test Allow if voice is in service if RAT is 2g/3g
serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_1XRTT,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null);
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
}
}