blob: b403e8d75bd9bce162ddd61e977ecbb9f11fc469 [file] [log] [blame]
/*
* Copyright (C) 2016 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.dataconnection;
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static com.android.internal.telephony.dataconnection.ApnSettingTest.createApnSetting;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ServiceInfo;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.hardware.radio.V1_0.SetupDataCallResult;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.provider.Telephony;
import android.support.test.filters.FlakyTest;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;
import com.android.internal.R;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.server.pm.PackageManagerService;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DcTrackerTest extends TelephonyTest {
private final static String[] sNetworkAttributes = new String[]{
"mobile,0,0,0,-1,true", "mobile_mms,2,0,2,60000,true",
"mobile_supl,3,0,2,60000,true", "mobile_dun,4,0,2,60000,true",
"mobile_hipri,5,0,3,60000,true", "mobile_fota,10,0,2,60000,true",
"mobile_ims,11,0,2,60000,true", "mobile_cbs,12,0,2,60000,true",
"mobile_ia,14,0,2,-1,true", "mobile_emergency,15,0,2,-1,true"};
private final static List<String> sApnTypes = Arrays.asList(
"default", "mms", "cbs", "fota", "supl", "ia", "emergency", "dun", "hipri", "ims");
private static final int LTE_BEARER_BITMASK = 1 << (ServiceState.RIL_RADIO_TECHNOLOGY_LTE - 1);
private static final int EHRPD_BEARER_BITMASK =
1 << (ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD - 1);
public static final String FAKE_APN1 = "FAKE APN 1";
public static final String FAKE_APN2 = "FAKE APN 2";
public static final String FAKE_APN3 = "FAKE APN 3";
public static final String FAKE_APN4 = "FAKE APN 4";
public static final String FAKE_APN5 = "FAKE APN 5";
public static final String FAKE_IFNAME = "FAKE IFNAME";
public static final String FAKE_PCSCF_ADDRESS = "22.33.44.55";
public static final String FAKE_GATEWAY = "11.22.33.44";
public static final String FAKE_DNS = "55.66.77.88";
public static final String FAKE_ADDRESS = "99.88.77.66";
private static final int NETWORK_TYPE_LTE_BITMASK =
1 << (TelephonyManager.NETWORK_TYPE_LTE - 1);
private static final int NETWORK_TYPE_EHRPD_BITMASK =
1 << (TelephonyManager.NETWORK_TYPE_EHRPD - 1);
private static final Uri PREFERAPN_URI = Uri.parse(
Telephony.Carriers.CONTENT_URI + "/preferapn");
private static final int DATA_ENABLED_CHANGED = 0;
@Mock
ISub mIsub;
@Mock
IBinder mBinder;
@Mock
NetworkRequest mNetworkRequest;
@Mock
SubscriptionInfo mSubscriptionInfo;
@Mock
ApnContext mApnContext;
@Mock
ApnSetting mApnSetting;
@Mock
DataConnection mDataConnection;
@Mock
PackageManagerService mMockPackageManagerInternal;
@Mock
Handler mHandler;
private DcTracker mDct;
private DcTrackerTestHandler mDcTrackerTestHandler;
private AlarmManager mAlarmManager;
private PersistableBundle mBundle;
private SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
private final ApnSettingContentProvider mApnSettingContentProvider =
new ApnSettingContentProvider();
private Message mMessage;
private void addDataService() {
CellularDataService cellularDataService = new CellularDataService();
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.packageName = "com.android.phone";
serviceInfo.permission = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
IntentFilter filter = new IntentFilter();
mContextFixture.addService(
DataService.DATA_SERVICE_INTERFACE,
null,
"com.android.phone",
cellularDataService.mBinder,
serviceInfo,
filter);
}
private class DcTrackerTestHandler extends HandlerThread {
private DcTrackerTestHandler(String name) {
super(name);
}
@Override
public void onLooperPrepared() {
mDct = new DcTracker(mPhone, TransportType.WWAN);
setReady(true);
}
}
private class ApnSettingContentProvider extends MockContentProvider {
private int mPreferredApnSet = 0;
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
logd("ApnSettingContentProvider: query");
logd(" uri = " + uri);
logd(" projection = " + Arrays.toString(projection));
logd(" selection = " + selection);
logd(" selectionArgs = " + Arrays.toString(selectionArgs));
logd(" sortOrder = " + sortOrder);
if (uri.compareTo(Telephony.Carriers.CONTENT_URI) == 0
|| uri.compareTo(Uri.withAppendedPath(
Telephony.Carriers.CONTENT_URI, "filtered")) == 0) {
if (projection == null && selectionArgs == null && selection != null) {
Pattern pattern = Pattern.compile("^numeric = '([0-9]*)'");
Matcher matcher = pattern.matcher(selection);
if (!matcher.find()) {
logd("Cannot find MCC/MNC from " + selection);
return null;
}
String plmn = matcher.group(1);
logd("Query '" + plmn + "' APN settings");
MatrixCursor mc = new MatrixCursor(
new String[]{Telephony.Carriers._ID, Telephony.Carriers.NUMERIC,
Telephony.Carriers.NAME, Telephony.Carriers.APN,
Telephony.Carriers.PROXY, Telephony.Carriers.PORT,
Telephony.Carriers.MMSC, Telephony.Carriers.MMSPROXY,
Telephony.Carriers.MMSPORT, Telephony.Carriers.USER,
Telephony.Carriers.PASSWORD, Telephony.Carriers.AUTH_TYPE,
Telephony.Carriers.TYPE,
Telephony.Carriers.PROTOCOL,
Telephony.Carriers.ROAMING_PROTOCOL,
Telephony.Carriers.CARRIER_ENABLED, Telephony.Carriers.BEARER,
Telephony.Carriers.BEARER_BITMASK,
Telephony.Carriers.PROFILE_ID,
Telephony.Carriers.MODEM_COGNITIVE,
Telephony.Carriers.MAX_CONNS, Telephony.Carriers.WAIT_TIME,
Telephony.Carriers.MAX_CONNS_TIME, Telephony.Carriers.MTU,
Telephony.Carriers.MVNO_TYPE,
Telephony.Carriers.MVNO_MATCH_DATA,
Telephony.Carriers.NETWORK_TYPE_BITMASK,
Telephony.Carriers.APN_SET_ID});
mc.addRow(new Object[]{
2163, // id
plmn, // numeric
"sp-mode", // name
FAKE_APN1, // apn
"", // proxy
"", // port
"", // mmsc
"", // mmsproxy
"", // mmsport
"", // user
"", // password
-1, // authtype
"default,supl", // types
"IP", // protocol
"IP", // roaming_protocol
1, // carrier_enabled
ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer
0, // bearer_bitmask
0, // profile_id
1, // modem_cognitive
0, // max_conns
0, // wait_time
0, // max_conns_time
0, // mtu
"", // mvno_type
"", // mnvo_match_data
NETWORK_TYPE_LTE_BITMASK, // network_type_bitmask
0 // apn_set_id
});
mc.addRow(new Object[]{
2164, // id
plmn, // numeric
"mopera U", // name
FAKE_APN2, // apn
"", // proxy
"", // port
"", // mmsc
"", // mmsproxy
"", // mmsport
"", // user
"", // password
-1, // authtype
"default,supl", // types
"IP", // protocol
"IP", // roaming_protocol
1, // carrier_enabled
ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer,
0, // bearer_bitmask
0, // profile_id
1, // modem_cognitive
0, // max_conns
0, // wait_time
0, // max_conns_time
0, // mtu
"", // mvno_type
"", // mnvo_match_data
NETWORK_TYPE_LTE_BITMASK, // network_type_bitmask
0 // apn_set_id
});
mc.addRow(new Object[]{
2165, // id
plmn, // numeric
"b-mobile for Nexus", // name
FAKE_APN3, // apn
"", // proxy
"", // port
"", // mmsc
"", // mmsproxy
"", // mmsport
"", // user
"", // password
-1, // authtype
"ims", // types
"IP", // protocol
"IP", // roaming_protocol
1, // carrier_enabled
0, // bearer
0, // bearer_bitmask
0, // profile_id
1, // modem_cognitive
0, // max_conns
0, // wait_time
0, // max_conns_time
0, // mtu
"", // mvno_type
"", // mnvo_match_data
0, // network_type_bitmask
0 // apn_set_id
});
mc.addRow(new Object[]{
2166, // id
plmn, // numeric
"sp-mode ehrpd", // name
FAKE_APN4, // apn
"", // proxy
"", // port
"", // mmsc
"", // mmsproxy
"", // mmsport
"", // user
"", // password
-1, // authtype
"default,supl", // types
"IP", // protocol
"IP", // roaming_protocol
1, // carrier_enabled
ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD, // bearer
0, // bearer_bitmask
0, // profile_id
1, // modem_cognitive
0, // max_conns
0, // wait_time
0, // max_conns_time
0, // mtu
"", // mvno_type
"", // mnvo_match_data
NETWORK_TYPE_EHRPD_BITMASK, // network_type_bitmask
0 // apn_set_id
});
mc.addRow(new Object[]{
2166, // id
plmn, // numeric
"b-mobile for Nexus", // name
FAKE_APN5, // apn
"", // proxy
"", // port
"", // mmsc
"", // mmsproxy
"", // mmsport
"", // user
"", // password
-1, // authtype
"dun", // types
"IP", // protocol
"IP", // roaming_protocol
1, // carrier_enabled
0, // bearer
0, // bearer_bitmask
0, // profile_id
1, // modem_cognitive
0, // max_conns
0, // wait_time
0, // max_conns_time
0, // mtu
"", // mvno_type
"", // mnvo_match_data
0, // network_type_bitmask
0 // apn_set_id
});
return mc;
}
} else if (uri.isPathPrefixMatch(
Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapnset"))) {
MatrixCursor mc = new MatrixCursor(
new String[]{Telephony.Carriers.APN_SET_ID});
// apn_set_id is the only field used with this URL
mc.addRow(new Object[]{ mPreferredApnSet });
mc.addRow(new Object[]{ 0 });
return mc;
}
return null;
}
@Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
mPreferredApnSet = values.getAsInteger(Telephony.Carriers.APN_SET_ID);
return 1;
}
}
@Before
public void setUp() throws Exception {
logd("DcTrackerTest +Setup!");
super.setUp(getClass().getSimpleName());
doReturn("fake.action_detached").when(mPhone).getActionDetached();
doReturn("fake.action_attached").when(mPhone).getActionAttached();
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
.getRilDataRadioTechnology();
doReturn("44010").when(mSimRecords).getOperatorNumeric();
mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
sNetworkAttributes);
mContextFixture.putStringArrayResource(com.android.internal.R.array.
config_mobile_tcp_buffers, new String[]{
"umts:131072,262144,1452032,4096,16384,399360",
"hspa:131072,262144,2441216,4096,16384,399360",
"hsupa:131072,262144,2441216,4096,16384,399360",
"hsdpa:131072,262144,2441216,4096,16384,399360",
"hspap:131072,262144,2441216,4096,16384,399360",
"edge:16384,32768,131072,4096,16384,65536",
"gprs:4096,8192,24576,4096,8192,24576",
"1xrtt:16384,32768,131070,4096,16384,102400",
"evdo:131072,262144,1048576,4096,16384,524288",
"lte:524288,1048576,8388608,262144,524288,4194304"});
mContextFixture.putResource(R.string.config_wwan_data_service_package,
"com.android.phone");
((MockContentResolver) mContext.getContentResolver()).addProvider(
Telephony.Carriers.CONTENT_URI.getAuthority(), mApnSettingContentProvider);
doReturn(true).when(mSimRecords).getRecordsLoaded();
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn(true).when(mSST).getDesiredPowerState();
doReturn(true).when(mSST).getPowerStateFromCarrier();
doAnswer(
new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
mOnSubscriptionsChangedListener =
(SubscriptionManager.OnSubscriptionsChangedListener)
invocation.getArguments()[0];
return null;
}
}
).when(mSubscriptionManager).addOnSubscriptionsChangedListener(any());
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
doReturn(1).when(mIsub).getDefaultDataSubId();
doReturn(mIsub).when(mBinder).queryLocalInterface(anyString());
mServiceManagerMockedServices.put("isub", mBinder);
mServiceManagerMockedServices.put("package", mMockPackageManagerInternal);
mContextFixture.putStringArrayResource(
com.android.internal.R.array.config_cell_retries_per_error_code,
new String[]{"36,2"});
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mBundle = mContextFixture.getCarrierConfigBundle();
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
addDataService();
mDcTrackerTestHandler = new DcTrackerTestHandler(getClass().getSimpleName());
mDcTrackerTestHandler.start();
waitUntilReady();
waitForMs(600);
logd("DcTrackerTest -Setup!");
}
@After
public void tearDown() throws Exception {
logd("DcTrackerTest -tearDown");
mDct.removeCallbacksAndMessages(null);
mDct = null;
mDcTrackerTestHandler.quit();
super.tearDown();
}
// Create a successful data response
private static SetupDataCallResult createSetupDataCallResult() throws Exception {
SetupDataCallResult result = new SetupDataCallResult();
result.status = 0;
result.suggestedRetryTime = -1;
result.cid = 1;
result.active = 2;
result.type = "IP";
result.ifname = FAKE_IFNAME;
result.addresses = FAKE_ADDRESS;
result.dnses = FAKE_DNS;
result.gateways = FAKE_GATEWAY;
result.pcscf = FAKE_PCSCF_ADDRESS;
result.mtu = 1440;
return result;
}
private void verifyDataProfile(DataProfile dp, String apn, int profileId,
int supportedApnTypesBitmap, int type, int bearerBitmask) {
assertEquals(profileId, dp.getProfileId());
assertEquals(apn, dp.getApn());
assertEquals("IP", dp.getProtocol());
assertEquals(0, dp.getAuthType());
assertEquals("", dp.getUserName());
assertEquals("", dp.getPassword());
assertEquals(type, dp.getType());
assertEquals(0, dp.getWaitTime());
assertTrue(dp.isEnabled());
assertEquals(supportedApnTypesBitmap, dp.getSupportedApnTypesBitmap());
assertEquals("IP", dp.getRoamingProtocol());
assertEquals(bearerBitmask, dp.getBearerBitmap());
assertEquals(0, dp.getMtu());
assertTrue(dp.isPersistent());
assertFalse(dp.isPreferred());
}
private void verifyDataConnected(final String apnSetting) {
verify(mPhone, times(1)).notifyDataConnection(eq(Phone.REASON_CONNECTED),
eq(PhoneConstants.APN_TYPE_DEFAULT));
verify(mAlarmManager, times(1)).set(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
any(PendingIntent.class));
assertEquals(apnSetting, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
assertArrayEquals(new String[]{PhoneConstants.APN_TYPE_DEFAULT}, mDct.getActiveApnTypes());
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
LinkProperties linkProperties = mDct.getLinkProperties(PhoneConstants.APN_TYPE_DEFAULT);
assertEquals(FAKE_IFNAME, linkProperties.getInterfaceName());
assertEquals(1, linkProperties.getAddresses().size());
assertEquals(FAKE_ADDRESS, linkProperties.getAddresses().get(0).getHostAddress());
assertEquals(1, linkProperties.getDnsServers().size());
assertEquals(FAKE_DNS, linkProperties.getDnsServers().get(0).getHostAddress());
assertEquals(FAKE_GATEWAY, linkProperties.getRoutes().get(0).getGateway().getHostAddress());
}
private boolean isDataAllowed(DataConnectionReasons dataConnectionReasons) {
try {
Method method = DcTracker.class.getDeclaredMethod("isDataAllowed",
DataConnectionReasons.class);
method.setAccessible(true);
return (boolean) method.invoke(mDct, dataConnectionReasons);
} catch (Exception e) {
fail(e.toString());
return false;
}
}
// Test the normal data call setup scenario.
@Test
@MediumTest
public void testDataSetup() throws Exception {
mDct.setUserDataEnabled(true);
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
boolean allowed = isDataAllowed(dataConnectionReasons);
assertFalse(dataConnectionReasons.toString(), allowed);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
ArgumentCaptor<String> apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_SIM_LOADED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_DATA_ATTACHED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_DATA_ENABLED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
logd("Sending EVENT_ENABLE_NEW_APN");
// APN id 0 is APN_TYPE_DEFAULT
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
waitForMs(200);
dataConnectionReasons = new DataConnectionReasons();
allowed = isDataAllowed(dataConnectionReasons);
assertTrue(dataConnectionReasons.toString(), allowed);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, LTE_BEARER_BITMASK);
verifyDataConnected(FAKE_APN1);
}
// Test the scenario where the first data call setup is failed, and then retry the setup later.
@Test
@MediumTest
public void testDataRetry() throws Exception {
mDct.setUserDataEnabled(true);
// LOST_CONNECTION(0x10004) is a non-permanent failure, so we'll retry data setup later.
/*DataCallResponse dcResponse = new DataCallResponse(0x10004, -1, 1, 2, "IP", FAKE_IFNAME,
Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
Arrays.asList(FAKE_PCSCF_ADDRESS),
1440);*/
SetupDataCallResult result = createSetupDataCallResult();
result.status = 0x10004;
// Simulate RIL fails the data call setup
mSimulatedCommands.setDataCallResult(false, result);
DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
boolean allowed = isDataAllowed(dataConnectionReasons);
assertFalse(dataConnectionReasons.toString(), allowed);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
ArgumentCaptor<String> apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_SIM_LOADED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_DATA_ATTACHED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
eq(Phone.REASON_DATA_ENABLED), apnTypeArgumentCaptor.capture(),
eq(PhoneConstants.DataState.DISCONNECTED));
assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
logd("Sending EVENT_ENABLE_NEW_APN");
// APN id 0 is APN_TYPE_DEFAULT
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
waitForMs(200);
dataConnectionReasons = new DataConnectionReasons();
allowed = isDataAllowed(dataConnectionReasons);
assertTrue(dataConnectionReasons.toString(), allowed);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, LTE_BEARER_BITMASK);
// Make sure we never notify connected because the data call setup is supposed to fail.
verify(mPhone, never()).notifyDataConnection(eq(Phone.REASON_CONNECTED),
eq(PhoneConstants.APN_TYPE_DEFAULT));
// Verify the retry manger schedule another data call setup.
verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(), any(PendingIntent.class));
// This time we'll let RIL command succeed.
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
// Simulate the timer expires.
Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
intent.putExtra("reconnect_alarm_extra_transport_type", TransportType.WWAN);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcast(intent);
waitForMs(200);
dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 21, 1, LTE_BEARER_BITMASK);
// Verify connected with APN2 setting.
verifyDataConnected(FAKE_APN2);
}
@Test
@MediumTest
@Ignore
@FlakyTest
public void testUserDisableData() throws Exception {
//step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
//set Default and MMS to be metered in the CarrierConfigManager
boolean dataEnabled = mDct.isUserDataEnabled();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
mDct.setEnabled(ApnSetting.TYPE_IMS, true);
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
logd("Sending DATA_ENABLED_CMD");
mDct.setUserDataEnabled(true);
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
logd("Sending DATA_DISABLED_CMD");
mDct.setUserDataEnabled(false);
waitForMs(200);
// expected tear down all metered DataConnections
verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
// reset the setting at the end of this test
mDct.setUserDataEnabled(dataEnabled);
waitForMs(200);
}
@Test
@MediumTest
public void testUserDisableRoaming() throws Exception {
//step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
//step 2: set roaming disabled, data is enabled
//step 3: under roaming service
//step 4: only tear down metered data connections.
//set Default and MMS to be metered in the CarrierConfigManager
boolean roamingEnabled = mDct.getDataRoamingEnabled();
boolean dataEnabled = mDct.isUserDataEnabled();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
mDct.setEnabled(ApnSetting.TYPE_IMS, true);
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
logd("Sending DATA_ENABLED_CMD");
mDct.setUserDataEnabled(true);
waitForMs(300);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, LTE_BEARER_BITMASK);
//user is in roaming
doReturn(true).when(mServiceState).getDataRoaming();
logd("Sending DISABLE_ROAMING_CMD");
mDct.setDataRoamingEnabledByUser(false);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_ROAMING_ON));
waitForMs(200);
// expected tear down all metered DataConnections
verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
// reset roaming settings / data enabled settings at end of this test
mDct.setDataRoamingEnabledByUser(roamingEnabled);
mDct.setUserDataEnabled(dataEnabled);
waitForMs(200);
}
@Test
@MediumTest
public void testDataCallOnUserDisableRoaming() throws Exception {
//step 1: mock under roaming service and user disabled roaming from settings.
//step 2: user toggled data settings on
//step 3: only non-metered data call is established
boolean roamingEnabled = mDct.getDataRoamingEnabled();
boolean dataEnabled = mDct.isUserDataEnabled();
doReturn(true).when(mServiceState).getDataRoaming();
//set Default and MMS to be metered in the CarrierConfigManager
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
mDct.setEnabled(ApnSetting.TYPE_IMS, true);
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
logd("Sending DATA_ENABLED_CMD");
mDct.setUserDataEnabled(true);
logd("Sending DISABLE_ROAMING_CMD");
mDct.setDataRoamingEnabledByUser(false);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
// reset roaming settings / data enabled settings at end of this test
mDct.setDataRoamingEnabledByUser(roamingEnabled);
mDct.setUserDataEnabled(dataEnabled);
waitForMs(200);
}
// Test the default data switch scenario.
@FlakyTest /* flakes 1.57% of the time */
@Test
@MediumTest
public void testDDSResetAutoAttach() throws Exception {
ContentResolver resolver = mContext.getContentResolver();
Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONED, 1);
mDct.setUserDataEnabled(true);
mContextFixture.putBooleanResource(
com.android.internal.R.bool.config_auto_attach_data_on_creation, true);
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
boolean allowed = isDataAllowed(dataConnectionReasons);
assertFalse(dataConnectionReasons.toString(), allowed);
ArgumentCaptor<Integer> intArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mUiccController, times(1)).registerForIccChanged(eq(mDct),
intArgumentCaptor.capture(), eq(null));
// Ideally this should send EVENT_ICC_CHANGED.
mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
waitForMs(100);
verify(mSimRecords, times(1)).registerForRecordsLoaded(eq(mDct),
intArgumentCaptor.capture(), eq(null));
// Ideally this should send EVENT_RECORDS_LOADED.
mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
waitForMs(100);
verify(mSST, times(1)).registerForDataConnectionAttached(eq(mDct),
intArgumentCaptor.capture(), eq(null));
// Ideally this should send EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
waitForMs(200);
NetworkRequest nr = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
LocalLog l = new LocalLog(100);
mDct.requestNetwork(nr, l);
waitForMs(200);
verifyDataConnected(FAKE_APN1);
assertTrue(mDct.getAutoAttachOnCreation());
mDct.update();
// The auto attach flag should be reset after update
assertFalse(mDct.getAutoAttachOnCreation());
verify(mSST, times(1)).registerForDataConnectionDetached(eq(mDct),
intArgumentCaptor.capture(), eq(null));
// Ideally this should send EVENT_DATA_CONNECTION_DETACHED
mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
waitForMs(200);
// Data should not be allowed since auto attach flag has been reset.
dataConnectionReasons = new DataConnectionReasons();
allowed = isDataAllowed(dataConnectionReasons);
assertFalse(dataConnectionReasons.toString(), allowed);
}
// Test for API carrierActionSetMeteredApnsEnabled.
@FlakyTest
@Ignore
@Test
@MediumTest
public void testCarrierActionSetMeteredApnsEnabled() throws Exception {
//step 1: setup two DataCalls one for Internet and IMS
//step 2: set data is enabled
//step 3: cold sim is detected
//step 4: all data connection is torn down
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
boolean dataEnabled = mDct.isUserDataEnabled();
mDct.setUserDataEnabled(true);
mDct.setEnabled(ApnSetting.TYPE_IMS, true);
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
Message msg = mDct.obtainMessage(DctConstants.EVENT_SET_CARRIER_DATA_ENABLED);
AsyncResult.forMessage(msg).result = false;
mDct.sendMessage(msg);
waitForMs(100);
// Validate all metered data connections have been torn down
verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
// Reset settings at the end of test
mDct.setUserDataEnabled(dataEnabled);
waitForMs(200);
}
private void initApns(String targetApn, String[] canHandleTypes) {
doReturn(targetApn).when(mApnContext).getApnType();
doReturn(true).when(mApnContext).isConnectable();
ApnSetting apnSetting = createApnSetting(ApnSetting.getApnTypesBitmaskFromString(
TextUtils.join(",", canHandleTypes)));
doReturn(apnSetting).when(mApnContext).getNextApnSetting();
doReturn(apnSetting).when(mApnContext).getApnSetting();
doReturn(mDataConnection).when(mApnContext).getDataConnection();
doReturn(true).when(mApnContext).isEnabled();
doReturn(true).when(mApnContext).getDependencyMet();
doReturn(true).when(mApnContext).isReady();
doReturn(true).when(mApnContext).hasNoRestrictedRequests(eq(true));
}
// Test the emergency APN setup.
@Test
@SmallTest
public void testTrySetupDataEmergencyApn() throws Exception {
initApns(PhoneConstants.APN_TYPE_EMERGENCY, new String[]{PhoneConstants.APN_TYPE_ALL});
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
@Test
@SmallTest
public void testGetDataConnectionState() throws Exception {
initApns(PhoneConstants.APN_TYPE_SUPL,
new String[]{PhoneConstants.APN_TYPE_SUPL, PhoneConstants.APN_TYPE_DEFAULT});
mDct.setUserDataEnabled(false);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
// Assert that both APN_TYPE_SUPL & APN_TYPE_DEFAULT are connected even we only setup data
// for APN_TYPE_SUPL
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_SUPL));
assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
}
// Test the unmetered APN setup when data is disabled.
@Test
@SmallTest
public void testTrySetupDataUnmeteredDataDisabled() throws Exception {
initApns(PhoneConstants.APN_TYPE_FOTA, new String[]{PhoneConstants.APN_TYPE_ALL});
mDct.setUserDataEnabled(false);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the metered APN setup when data is disabled.
@Test
@SmallTest
public void testTrySetupMeteredDataDisabled() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
mDct.setUserDataEnabled(false);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the restricted data request when data is disabled.
@Test
@SmallTest
public void testTrySetupRestrictedDataDisabled() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
doReturn(false).when(mApnContext).hasNoRestrictedRequests(eq(true));
mDct.setUserDataEnabled(false);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the restricted data request when roaming is disabled.
@Test
@SmallTest
public void testTrySetupRestrictedRoamingDisabled() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
doReturn(false).when(mApnContext).hasNoRestrictedRequests(eq(true));
mDct.setUserDataEnabled(true);
mDct.setDataRoamingEnabledByUser(false);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
//user is in roaming
doReturn(true).when(mServiceState).getDataRoaming();
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
// expect no restricted data connection
verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the default data when data is not connectable.
@Test
@SmallTest
public void testTrySetupNotConnectable() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
doReturn(false).when(mApnContext).isConnectable();
mDct.setUserDataEnabled(true);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the default data on IWLAN.
@Test
@SmallTest
public void testTrySetupDefaultOnIWLAN() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN).when(mServiceState)
.getRilDataRadioTechnology();
mDct.setUserDataEnabled(true);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test the default data when the phone is in ECBM.
@Test
@SmallTest
public void testTrySetupDefaultInECBM() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
doReturn(true).when(mPhone).isInEcm();
mDct.setUserDataEnabled(true);
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
}
// Test update waiting apn list when on data rat change
@FlakyTest /* flakes 0.86% of the time */
@Test
@SmallTest
public void testUpdateWaitingApnListOnDataRatChange() throws Exception {
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
.getRilDataRadioTechnology();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
mDct.setUserDataEnabled(true);
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, EHRPD_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
//data rat change from ehrpd to lte
logd("Sending EVENT_DATA_RAT_CHANGED");
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
.getRilDataRadioTechnology();
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
waitForMs(200);
// Verify the disconnected data call due to rat change and retry manger schedule another
// data call setup
verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(), any(PendingIntent.class));
// Simulate the timer expires.
Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
intent.putExtra("reconnect_alarm_extra_transport_type", TransportType.WWAN);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcast(intent);
waitForMs(200);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, LTE_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
}
// Test for fetchDunApns()
@Test
@SmallTest
public void testFetchDunApn() {
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
String dunApnString = "[ApnSettingV3]HOT mobile PC,pc.hotm,,,,,,,,,440,10,,DUN,,,true,"
+ "0,,,,,,,,";
ApnSetting dunApnExpected = ApnSetting.fromString(dunApnString);
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.TETHER_DUN_APN, dunApnString);
// should return APN from Setting
ApnSetting dunApn = mDct.fetchDunApns().get(0);
assertTrue(dunApnExpected.equals(dunApn));
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.TETHER_DUN_APN, null);
// should return APN from db
dunApn = mDct.fetchDunApns().get(0);
assertEquals(FAKE_APN5, dunApn.getApnName());
}
// Test for fetchDunApns() with apn set id
@Test
@SmallTest
public void testFetchDunApnWithPreferredApnSet() {
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
// apnSetId=1
String dunApnString1 = "[ApnSettingV5]HOT mobile PC,pc.hotm,,,,,,,,,440,10,,DUN,,,true,"
+ "0,,,,,,,,,,1";
// apnSetId=0
String dunApnString2 = "[ApnSettingV5]HOT mobile PC,pc.coldm,,,,,,,,,440,10,,DUN,,,true,"
+ "0,,,,,,,,,,0";
ApnSetting dunApnExpected = ApnSetting.fromString(dunApnString1);
ContentResolver cr = mContext.getContentResolver();
Settings.Global.putString(cr, Settings.Global.TETHER_DUN_APN,
dunApnString1 + ";" + dunApnString2);
// set that we prefer apn set 1
ContentValues values = new ContentValues();
values.put(Telephony.Carriers.APN_SET_ID, 1);
cr.update(PREFERAPN_URI, values, null, null);
// return APN from Setting with apnSetId=1
ArrayList<ApnSetting> dunApns = mDct.sortApnListByPreferred(mDct.fetchDunApns());
assertEquals(2, dunApns.size());
assertTrue(dunApnExpected.equals(dunApns.get(0)));
}
// Test oos
@Test
@SmallTest
public void testDataRatChangeOOS() throws Exception {
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
.getRilDataRadioTechnology();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{PhoneConstants.APN_TYPE_DEFAULT});
mDct.setEnabled(ApnSetting.TYPE_DEFAULT, true);
mDct.setUserDataEnabled(true);
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
logd("Sending EVENT_RECORDS_LOADED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
waitForMs(200);
logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
waitForMs(200);
ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
// Verify if RIL command was sent properly.
verify(mSimulatedCommandsVerifier).setupDataCall(
eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, EHRPD_BEARER_BITMASK);
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
// Data rat change from ehrpd to unknown due to OOS
logd("Sending EVENT_DATA_RAT_CHANGED");
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN).when(mServiceState)
.getRilDataRadioTechnology();
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
waitForMs(200);
// Verify data connection is on
verify(mSimulatedCommandsVerifier, times(0)).deactivateDataCall(
eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
any(Message.class));
// Data rat resume from unknown to ehrpd
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
.getRilDataRadioTechnology();
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
waitForMs(200);
// Verify the same data connection
assertEquals(FAKE_APN4, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
}
// Test provisioning
@Test
@SmallTest
public void testDataEnableInProvisioning() throws Exception {
ContentResolver resolver = mContext.getContentResolver();
assertEquals(1, Settings.Global.getInt(resolver, Settings.Global.MOBILE_DATA));
assertTrue(mDct.isDataEnabled());
assertTrue(mDct.isUserDataEnabled());
mDct.setUserDataEnabled(false);
waitForMs(200);
assertEquals(0, Settings.Global.getInt(resolver, Settings.Global.MOBILE_DATA));
assertFalse(mDct.isDataEnabled());
assertFalse(mDct.isUserDataEnabled());
// Changing provisioned to 0.
Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE, null));
waitForMs(200);
assertTrue(mDct.isDataEnabled());
assertTrue(mDct.isUserDataEnabled());
// Enable user data during provisioning. It should write to
// Settings.Global.MOBILE_DATA and keep data enabled when provisioned.
mDct.setUserDataEnabled(true);
Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONED, 1);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE, null));
waitForMs(200);
assertTrue(mDct.isDataEnabled());
assertTrue(mDct.isUserDataEnabled());
assertEquals(1, Settings.Global.getInt(resolver, Settings.Global.MOBILE_DATA));
}
@Test
@SmallTest
public void testNotifyDataEnabledChanged() throws Exception {
doAnswer(invocation -> {
mMessage = (Message) invocation.getArguments()[0];
return true;
}).when(mHandler).sendMessageDelayed(any(), anyLong());
// Test registration.
mDct.registerForDataEnabledChanged(mHandler, DATA_ENABLED_CHANGED, null);
verifyDataEnabledChangedMessage(true, DataEnabledSettings.REASON_REGISTERED);
// Disable user data. Should receive data enabled change to false.
mDct.setUserDataEnabled(false);
waitForMs(200);
verifyDataEnabledChangedMessage(false, DataEnabledSettings.REASON_USER_DATA_ENABLED);
// Changing provisioned to 0. Shouldn't receive any message, as data enabled remains false.
ContentResolver resolver = mContext.getContentResolver();
Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0);
Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
0);
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE, null));
waitForMs(200);
assertFalse(mDct.isDataEnabled());
verify(mHandler, never()).sendMessageDelayed(any(), anyLong());
// Changing provisioningDataEnabled to 1. It should trigger data enabled change to true.
Settings.Global.putInt(resolver,
Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, 1);
mDct.sendMessage(mDct.obtainMessage(
DctConstants.EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE, null));
waitForMs(200);
verifyDataEnabledChangedMessage(
true, DataEnabledSettings.REASON_PROVISIONING_DATA_ENABLED_CHANGED);
}
private void verifyDataEnabledChangedMessage(boolean enabled, int reason) {
verify(mHandler, times(1)).sendMessageDelayed(any(), anyLong());
Pair<Boolean, Integer> result = (Pair) ((AsyncResult) mMessage.obj).result;
assertEquals(DATA_ENABLED_CHANGED, mMessage.what);
assertEquals(enabled, result.first);
assertEquals(reason, (int) result.second);
clearInvocations(mHandler);
}
}