Home | History | Annotate | Download | only in dataconnection
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.dataconnection;
     18 
     19 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
     20 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
     21 import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
     22 import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
     23 
     24 import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
     25 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_ADDRESS;
     26 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_DNS;
     27 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_GATEWAY;
     28 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME;
     29 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS;
     30 
     31 import static org.junit.Assert.assertEquals;
     32 import static org.junit.Assert.assertFalse;
     33 import static org.junit.Assert.assertTrue;
     34 import static org.mockito.ArgumentMatchers.any;
     35 import static org.mockito.ArgumentMatchers.anyInt;
     36 import static org.mockito.ArgumentMatchers.eq;
     37 import static org.mockito.Mockito.doReturn;
     38 import static org.mockito.Mockito.mock;
     39 import static org.mockito.Mockito.times;
     40 import static org.mockito.Mockito.verify;
     41 
     42 import android.content.IntentFilter;
     43 import android.content.pm.ServiceInfo;
     44 import android.net.KeepalivePacketData;
     45 import android.net.LinkAddress;
     46 import android.net.LinkProperties;
     47 import android.net.NetworkCapabilities;
     48 import android.net.NetworkInfo;
     49 import android.net.NetworkUtils;
     50 import android.os.AsyncResult;
     51 import android.os.Handler;
     52 import android.os.HandlerThread;
     53 import android.os.Message;
     54 import android.telephony.AccessNetworkConstants.AccessNetworkType;
     55 import android.telephony.AccessNetworkConstants.TransportType;
     56 import android.telephony.CarrierConfigManager;
     57 import android.telephony.ServiceState;
     58 import android.telephony.data.DataCallResponse;
     59 import android.telephony.data.DataProfile;
     60 import android.telephony.data.DataService;
     61 import android.test.suitebuilder.annotation.MediumTest;
     62 import android.test.suitebuilder.annotation.SmallTest;
     63 
     64 import com.android.internal.R;
     65 import com.android.internal.telephony.PhoneConstants;
     66 import com.android.internal.telephony.RetryManager;
     67 import com.android.internal.telephony.TelephonyTest;
     68 import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams;
     69 import com.android.internal.telephony.dataconnection.DataConnection.DisconnectParams;
     70 import com.android.internal.telephony.dataconnection.DataConnection.SetupResult;
     71 import com.android.internal.util.IState;
     72 import com.android.internal.util.StateMachine;
     73 import com.android.server.pm.PackageManagerService;
     74 
     75 import org.junit.After;
     76 import org.junit.Before;
     77 import org.junit.Test;
     78 import org.mockito.ArgumentCaptor;
     79 import org.mockito.Mock;
     80 
     81 import java.lang.reflect.Field;
     82 import java.lang.reflect.Method;
     83 import java.util.Arrays;
     84 
     85 public class DataConnectionTest extends TelephonyTest {
     86 
     87     @Mock
     88     DcTesterFailBringUpAll mDcTesterFailBringUpAll;
     89     @Mock
     90     ConnectionParams mCp;
     91     @Mock
     92     DisconnectParams mDcp;
     93     @Mock
     94     ApnContext mApnContext;
     95     @Mock
     96     DcFailBringUp mDcFailBringUp;
     97     @Mock
     98     PackageManagerService mMockPackageManagerInternal;
     99 
    100     private DataConnection mDc;
    101     private DataConnectionTestHandler mDataConnectionTestHandler;
    102     private DcController mDcc;
    103 
    104     private ApnSetting mApn1 = new ApnSetting(
    105             2163,                   // id
    106             "44010",                // numeric
    107             "sp-mode",              // name
    108             "spmode.ne.jp",         // apn
    109             "",                     // proxy
    110             "",                     // port
    111             "",                     // mmsc
    112             "",                     // mmsproxy
    113             "",                     // mmsport
    114             "",                     // user
    115             "",                     // password
    116             -1,                     // authtype
    117             new String[]{"default", "supl"},     // types
    118             "IP",                   // protocol
    119             "IP",                   // roaming_protocol
    120             true,                   // carrier_enabled
    121             0,                      // bearer
    122             0,                      // bearer_bitmask
    123             0,                      // profile_id
    124             false,                  // modem_cognitive
    125             0,                      // max_conns
    126             0,                      // wait_time
    127             0,                      // max_conns_time
    128             0,                      // mtu
    129             "",                     // mvno_type
    130             "");                    // mnvo_match_data
    131 
    132     private ApnSetting mApn2 = new ApnSetting(
    133             2164,                   // id
    134             "44010",                // numeric
    135             "sp-mode",              // name
    136             "spmode.ne.jp",         // apn
    137             "",                     // proxy
    138             "",                     // port
    139             "",                     // mmsc
    140             "",                     // mmsproxy
    141             "",                     // mmsport
    142             "",                     // user
    143             "",                     // password
    144             -1,                     // authtype
    145             new String[]{"default", "dun"},     // types
    146             "IP",                   // protocol
    147             "IP",                   // roaming_protocol
    148             true,                   // carrier_enabled
    149             0,                      // bearer
    150             0,                      // bearer_bitmask
    151             0,                      // profile_id
    152             false,                  // modem_cognitive
    153             0,                      // max_conns
    154             0,                      // wait_time
    155             0,                      // max_conns_time
    156             0,                      // mtu
    157             "",                     // mvno_type
    158             "");                    // mnvo_match_data
    159 
    160     private class DataConnectionTestHandler extends HandlerThread {
    161 
    162         private DataConnectionTestHandler(String name) {
    163             super(name);
    164         }
    165 
    166         @Override
    167         public void onLooperPrepared() {
    168             Handler h = new Handler();
    169 
    170             DataServiceManager manager = new DataServiceManager(mPhone, TransportType.WWAN);
    171             mDcc = DcController.makeDcc(mPhone, mDcTracker, manager, h);
    172             mDcc.start();
    173             mDc = DataConnection.makeDataConnection(mPhone, 0, mDcTracker, manager,
    174                     mDcTesterFailBringUpAll, mDcc);
    175         }
    176     }
    177 
    178     private void addDataService() {
    179         CellularDataService cellularDataService = new CellularDataService();
    180         ServiceInfo serviceInfo = new ServiceInfo();
    181         serviceInfo.packageName = "com.android.phone";
    182         serviceInfo.permission = "android.permission.BIND_DATA_SERVICE";
    183         IntentFilter filter = new IntentFilter();
    184         mContextFixture.addService(
    185                 DataService.DATA_SERVICE_INTERFACE,
    186                 null,
    187                 "com.android.phone",
    188                 cellularDataService.mBinder,
    189                 serviceInfo,
    190                 filter);
    191     }
    192 
    193 
    194     @Before
    195     public void setUp() throws Exception {
    196         logd("+Setup!");
    197         super.setUp(getClass().getSimpleName());
    198         mServiceManagerMockedServices.put("package", mMockPackageManagerInternal);
    199         doReturn("fake.action_detached").when(mPhone).getActionDetached();
    200         replaceInstance(ConnectionParams.class, "mApnContext", mCp, mApnContext);
    201         replaceInstance(ConnectionParams.class, "mRilRat", mCp,
    202                 ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
    203         doReturn(mApn1).when(mApnContext).getApnSetting();
    204         doReturn(PhoneConstants.APN_TYPE_DEFAULT).when(mApnContext).getApnType();
    205         doReturn(true).when(mDcTracker).isDataEnabled();
    206 
    207         mDcFailBringUp.saveParameters(0, 0, -2);
    208         doReturn(mDcFailBringUp).when(mDcTesterFailBringUpAll).getDcFailBringUp();
    209 
    210         mContextFixture.putStringArrayResource(com.android.internal.R.array.
    211                 config_mobile_tcp_buffers, new String[]{
    212                 "umts:131072,262144,1452032,4096,16384,399360",
    213                 "hspa:131072,262144,2441216,4096,16384,399360",
    214                 "hsupa:131072,262144,2441216,4096,16384,399360",
    215                 "hsdpa:131072,262144,2441216,4096,16384,399360",
    216                 "hspap:131072,262144,2441216,4096,16384,399360",
    217                 "edge:16384,32768,131072,4096,16384,65536",
    218                 "gprs:4096,8192,24576,4096,8192,24576",
    219                 "1xrtt:16384,32768,131070,4096,16384,102400",
    220                 "evdo:131072,262144,1048576,4096,16384,524288",
    221                 "lte:524288,1048576,8388608,262144,524288,4194304"});
    222 
    223         mContextFixture.putResource(R.string.config_wwan_data_service_package,
    224                 "com.android.phone");
    225 
    226         mDcp.mApnContext = mApnContext;
    227 
    228         addDataService();
    229 
    230         mDataConnectionTestHandler = new DataConnectionTestHandler(getClass().getSimpleName());
    231         mDataConnectionTestHandler.start();
    232 
    233         waitForMs(200);
    234         logd("-Setup!");
    235     }
    236 
    237     @After
    238     public void tearDown() throws Exception {
    239         logd("tearDown");
    240         mDc = null;
    241         mDcc = null;
    242         mDataConnectionTestHandler.quit();
    243         super.tearDown();
    244     }
    245 
    246     private IState getCurrentState() throws Exception {
    247         Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
    248         method.setAccessible(true);
    249         return (IState) method.invoke(mDc);
    250     }
    251 
    252     private long getSuggestedRetryDelay(DataCallResponse response) throws Exception {
    253         Class[] cArgs = new Class[1];
    254         cArgs[0] = DataCallResponse.class;
    255         Method method = DataConnection.class.getDeclaredMethod("getSuggestedRetryDelay", cArgs);
    256         method.setAccessible(true);
    257         return (long) method.invoke(mDc, response);
    258     }
    259 
    260     private SetupResult setLinkProperties(DataCallResponse response,
    261                                                          LinkProperties linkProperties)
    262             throws Exception {
    263         Class[] cArgs = new Class[2];
    264         cArgs[0] = DataCallResponse.class;
    265         cArgs[1] = LinkProperties.class;
    266         Method method = DataConnection.class.getDeclaredMethod("setLinkProperties", cArgs);
    267         method.setAccessible(true);
    268         return (SetupResult) method.invoke(mDc, response, linkProperties);
    269     }
    270 
    271     @Test
    272     @SmallTest
    273     public void testSanity() throws Exception {
    274         assertEquals("DcInactiveState", getCurrentState().getName());
    275     }
    276 
    277     @Test
    278     @SmallTest
    279     public void testConnectEvent() throws Exception {
    280         testSanity();
    281 
    282         mDc.sendMessage(DataConnection.EVENT_CONNECT, mCp);
    283         waitForMs(200);
    284 
    285         verify(mCT, times(1)).registerForVoiceCallStarted(any(Handler.class),
    286                 eq(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED), eq(null));
    287         verify(mCT, times(1)).registerForVoiceCallEnded(any(Handler.class),
    288                 eq(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED), eq(null));
    289         verify(mSimulatedCommandsVerifier, times(1))
    290                 .registerForNattKeepaliveStatus(any(Handler.class),
    291                         eq(DataConnection.EVENT_KEEPALIVE_STATUS), eq(null));
    292         verify(mSimulatedCommandsVerifier, times(1))
    293                 .registerForLceInfo(any(Handler.class),
    294                         eq(DataConnection.EVENT_LINK_CAPACITY_CHANGED), eq(null));
    295 
    296         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
    297         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
    298                 eq(AccessNetworkType.UTRAN), dpCaptor.capture(), eq(false),
    299                 eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(), any(Message.class));
    300 
    301         assertEquals("spmode.ne.jp", dpCaptor.getValue().getApn());
    302 
    303         assertEquals("DcActiveState", getCurrentState().getName());
    304     }
    305 
    306     @Test
    307     @SmallTest
    308     public void testDisconnectEvent() throws Exception {
    309         testConnectEvent();
    310 
    311         mDc.sendMessage(DataConnection.EVENT_DISCONNECT, mDcp);
    312         waitForMs(100);
    313 
    314         verify(mSimulatedCommandsVerifier, times(1)).unregisterForLceInfo(any(Handler.class));
    315         verify(mSimulatedCommandsVerifier, times(1))
    316                 .unregisterForNattKeepaliveStatus(any(Handler.class));
    317         verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(eq(1),
    318                 eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
    319 
    320         assertEquals("DcInactiveState", getCurrentState().getName());
    321     }
    322 
    323     @Test
    324     @SmallTest
    325     public void testModemSuggestRetry() throws Exception {
    326         DataCallResponse response = new DataCallResponse(0, 0, 1, 2, "IP", FAKE_IFNAME,
    327                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    328                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    329                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    330                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    331                 1440);
    332 
    333         assertEquals(response.getSuggestedRetryTime(), getSuggestedRetryDelay(response));
    334 
    335         response = new DataCallResponse(0, 1000, 1, 2, "IP", FAKE_IFNAME,
    336                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    337                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    338                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    339                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    340                 1440);
    341         assertEquals(response.getSuggestedRetryTime(), getSuggestedRetryDelay(response));
    342 
    343         response = new DataCallResponse(0, 9999, 1, 2, "IP", FAKE_IFNAME,
    344                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    345                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    346                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    347                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    348                 1440);
    349         assertEquals(response.getSuggestedRetryTime(), getSuggestedRetryDelay(response));
    350     }
    351 
    352     @Test
    353     @SmallTest
    354     public void testModemNotSuggestRetry() throws Exception {
    355         DataCallResponse response = new DataCallResponse(0, -1, 1, 2, "IP", FAKE_IFNAME,
    356                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    357                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    358                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    359                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    360                 1440);
    361 
    362         assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, getSuggestedRetryDelay(response));
    363 
    364         response = new DataCallResponse(0, -5, 1, 2, "IP", FAKE_IFNAME,
    365                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    366                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    367                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    368                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    369                 1440);
    370         assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, getSuggestedRetryDelay(response));
    371 
    372         response = new DataCallResponse(0, Integer.MIN_VALUE, 1, 2, "IP", FAKE_IFNAME,
    373                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    374                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    375                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    376                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    377                 1440);
    378         assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, getSuggestedRetryDelay(response));
    379     }
    380 
    381     @Test
    382     @SmallTest
    383     public void testModemSuggestNoRetry() throws Exception {
    384         DataCallResponse response = new DataCallResponse(0, Integer.MAX_VALUE, 1, 2, "IP",
    385                 FAKE_IFNAME,
    386                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    387                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    388                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    389                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    390                 1440);
    391         assertEquals(RetryManager.NO_RETRY, getSuggestedRetryDelay(response));
    392     }
    393 
    394     private NetworkInfo getNetworkInfo() throws Exception {
    395         Field f = DataConnection.class.getDeclaredField("mNetworkInfo");
    396         f.setAccessible(true);
    397         return (NetworkInfo) f.get(mDc);
    398     }
    399 
    400     private NetworkCapabilities getNetworkCapabilities() throws Exception {
    401         Method method = DataConnection.class.getDeclaredMethod("getNetworkCapabilities");
    402         method.setAccessible(true);
    403         return (NetworkCapabilities) method.invoke(mDc);
    404     }
    405 
    406     @Test
    407     @SmallTest
    408     public void testNetworkCapability() throws Exception {
    409         mContextFixture.getCarrierConfigBundle().putStringArray(
    410                 CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
    411                 new String[] { "default" });
    412         doReturn(mApn2).when(mApnContext).getApnSetting();
    413         testConnectEvent();
    414 
    415         assertTrue("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    416                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN));
    417         assertTrue("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    418                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
    419         assertFalse("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    420                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS));
    421 
    422         mDc.sendMessage(DataConnection.EVENT_DISCONNECT, mDcp);
    423         waitForMs(100);
    424         doReturn(mApn1).when(mApnContext).getApnSetting();
    425         mDc.sendMessage(DataConnection.EVENT_CONNECT, mCp);
    426         waitForMs(200);
    427 
    428         assertFalse("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    429                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN));
    430         assertTrue("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    431                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
    432         assertTrue("capabilities: " + getNetworkCapabilities(), getNetworkCapabilities()
    433                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL));
    434     }
    435 
    436     @Test
    437     @SmallTest
    438     public void testMeteredCapability() throws Exception {
    439 
    440         mContextFixture.getCarrierConfigBundle().
    441                 putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
    442                 new String[] {"default"});
    443 
    444         testConnectEvent();
    445 
    446         assertFalse(getNetworkCapabilities()
    447                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
    448     }
    449 
    450     @Test
    451     @SmallTest
    452     public void testNonMeteredCapability() throws Exception {
    453 
    454         doReturn(2819).when(mPhone).getSubId();
    455         mContextFixture.getCarrierConfigBundle().
    456                 putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
    457                         new String[] {"mms"});
    458 
    459         testConnectEvent();
    460 
    461         assertTrue(getNetworkCapabilities()
    462                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
    463     }
    464 
    465     @Test
    466     public void testOverrideUnmetered() throws Exception {
    467         mContextFixture.getCarrierConfigBundle().putStringArray(
    468                 CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
    469                 new String[] { "default" });
    470         testConnectEvent();
    471 
    472         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    473         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    474 
    475         mDc.onSubscriptionOverride(OVERRIDE_UNMETERED, OVERRIDE_UNMETERED);
    476 
    477         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    478         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    479 
    480         mDc.onSubscriptionOverride(OVERRIDE_UNMETERED, 0);
    481 
    482         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    483         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    484     }
    485 
    486     @Test
    487     public void testOverrideCongested() throws Exception {
    488         mContextFixture.getCarrierConfigBundle().putStringArray(
    489                 CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
    490                 new String[] { "default" });
    491         testConnectEvent();
    492 
    493         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    494         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    495 
    496         mDc.onSubscriptionOverride(OVERRIDE_CONGESTED, OVERRIDE_CONGESTED);
    497 
    498         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    499         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    500 
    501         mDc.onSubscriptionOverride(OVERRIDE_CONGESTED, 0);
    502 
    503         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
    504         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
    505     }
    506 
    507     @SmallTest
    508     public void testIsIpAddress() throws Exception {
    509         // IPv4
    510         assertTrue(DataConnection.isIpAddress("1.2.3.4"));
    511         assertTrue(DataConnection.isIpAddress("127.0.0.1"));
    512 
    513         // IPv6
    514         assertTrue(DataConnection.isIpAddress("::1"));
    515         assertTrue(DataConnection.isIpAddress("2001:4860:800d::68"));
    516     }
    517 
    518     @Test
    519     @SmallTest
    520     public void testSetLinkProperties() throws Exception {
    521 
    522         DataCallResponse response = new DataCallResponse(0, -1, 1, 2, "IP", FAKE_IFNAME,
    523                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    524                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    525                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    526                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    527                 1440);
    528 
    529         LinkProperties linkProperties = new LinkProperties();
    530         assertEquals(SetupResult.SUCCESS, setLinkProperties(response, linkProperties));
    531         logd(linkProperties.toString());
    532         assertEquals(response.getIfname(), linkProperties.getInterfaceName());
    533         assertEquals(response.getAddresses().size(), linkProperties.getAddresses().size());
    534         for (int i = 0; i < response.getAddresses().size(); ++i) {
    535             assertEquals(response.getAddresses().get(i).getAddress(),
    536                     NetworkUtils.numericToInetAddress(linkProperties.getLinkAddresses().get(i)
    537                             .getAddress().getHostAddress()));
    538         }
    539 
    540         assertEquals(response.getDnses().size(), linkProperties.getDnsServers().size());
    541         for (int i = 0; i < response.getDnses().size(); ++i) {
    542             assertEquals("i = " + i, response.getDnses().get(i), NetworkUtils.numericToInetAddress(
    543                     linkProperties.getDnsServers().get(i).getHostAddress()));
    544         }
    545 
    546         assertEquals(response.getGateways().size(), linkProperties.getRoutes().size());
    547         for (int i = 0; i < response.getGateways().size(); ++i) {
    548             assertEquals("i = " + i, response.getGateways().get(i),
    549                     NetworkUtils.numericToInetAddress(linkProperties.getRoutes().get(i)
    550                             .getGateway().getHostAddress()));
    551         }
    552 
    553         assertEquals(response.getMtu(), linkProperties.getMtu());
    554     }
    555 
    556     @Test
    557     @SmallTest
    558     public void testSetLinkPropertiesEmptyAddress() throws Exception {
    559 
    560         // 224.224.224.224 is an invalid address.
    561         DataCallResponse response = new DataCallResponse(0, -1, 1, 2, "IP", FAKE_IFNAME,
    562                 null,
    563                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_DNS)),
    564                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    565                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    566                 1440);
    567 
    568         LinkProperties linkProperties = new LinkProperties();
    569         assertEquals(SetupResult.ERROR_INVALID_ARG,
    570                 setLinkProperties(response, linkProperties));
    571     }
    572 
    573     @Test
    574     @SmallTest
    575     public void testSetLinkPropertiesEmptyDns() throws Exception {
    576 
    577         // Empty dns entry.
    578         DataCallResponse response = new DataCallResponse(0, -1, 1, 2, "IP", FAKE_IFNAME,
    579                 Arrays.asList(new LinkAddress(NetworkUtils.numericToInetAddress(FAKE_ADDRESS), 0)),
    580                 null,
    581                 Arrays.asList(NetworkUtils.numericToInetAddress(FAKE_GATEWAY)),
    582                 Arrays.asList(FAKE_PCSCF_ADDRESS),
    583                 1440);
    584 
    585         // Make sure no exception was thrown
    586         LinkProperties linkProperties = new LinkProperties();
    587         assertEquals(SetupResult.SUCCESS, setLinkProperties(response, linkProperties));
    588     }
    589 
    590     @Test
    591     @SmallTest
    592     public void testStartKeepaliveWLAN() throws Exception {
    593         testConnectEvent();
    594         waitForMs(200);
    595 
    596         DataServiceManager mockDsm = mock(DataServiceManager.class);
    597         doReturn(TransportType.WLAN).when(mockDsm).getTransportType();
    598         replaceInstance(DataConnection.class, "mDataServiceManager", mDc, mockDsm);
    599 
    600         final int sessionHandle = 0xF00;
    601         final int slotId = 3;
    602         final int interval = 10; // seconds
    603         // Construct a new KeepalivePacketData request as we would receive from a Network Agent,
    604         // and check that the packet is sent to the RIL.
    605         KeepalivePacketData kd = KeepalivePacketData.nattKeepalivePacket(
    606                 NetworkUtils.numericToInetAddress("1.2.3.4"),
    607                 1234,
    608                 NetworkUtils.numericToInetAddress("8.8.8.8"),
    609                 4500);
    610         mDc.obtainMessage(
    611                 DataConnection.EVENT_KEEPALIVE_START_REQUEST, slotId, interval, kd).sendToTarget();
    612         waitForMs(100);
    613         // testStartStopNattKeepalive() verifies that this request is passed with WWAN.
    614         // Thus, even though we can't see the response in NetworkAgent, we can verify that the
    615         // CommandsInterface never receives a request and infer that it was dropped due to WLAN.
    616         verify(mSimulatedCommandsVerifier, times(0))
    617                 .startNattKeepalive(anyInt(), eq(kd), eq(interval * 1000), any(Message.class));
    618     }
    619 
    620     public void checkStartStopNattKeepalive(boolean useCondensedFlow) throws Exception {
    621         testConnectEvent();
    622         waitForMs(200);
    623 
    624         final int sessionHandle = 0xF00;
    625         final int slotId = 3;
    626         final int interval = 10; // seconds
    627         // Construct a new KeepalivePacketData request as we would receive from a Network Agent,
    628         // and check that the packet is sent to the RIL.
    629         KeepalivePacketData kd = KeepalivePacketData.nattKeepalivePacket(
    630                 NetworkUtils.numericToInetAddress("1.2.3.4"),
    631                 1234,
    632                 NetworkUtils.numericToInetAddress("8.8.8.8"),
    633                 4500);
    634         mDc.obtainMessage(
    635                 DataConnection.EVENT_KEEPALIVE_START_REQUEST, slotId, interval, kd).sendToTarget();
    636         waitForMs(100);
    637         verify(mSimulatedCommandsVerifier, times(1))
    638                 .startNattKeepalive(anyInt(), eq(kd), eq(interval * 1000), any(Message.class));
    639 
    640         Message kaStarted = mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STARTED, slotId, 0);
    641         if (useCondensedFlow) {
    642             // Send a singled condensed response that a keepalive have been requested and the
    643             // activation is completed. This flow should be used if the keepalive offload request
    644             // is handled by a high-priority signalling path.
    645             AsyncResult.forMessage(
    646                     kaStarted, new KeepaliveStatus(
    647                             sessionHandle, KeepaliveStatus.STATUS_ACTIVE), null);
    648             kaStarted.sendToTarget();
    649         } else {
    650             // Send the sequential responses indicating first that the request was received and
    651             // then that the keepalive is running. This should create an active record of the
    652             // keepalive in DataConnection while permitting the status from a low priority or other
    653             // high-latency handler to activate the keepalive without blocking a request.
    654             AsyncResult.forMessage(
    655                     kaStarted, new KeepaliveStatus(
    656                             sessionHandle, KeepaliveStatus.STATUS_PENDING), null);
    657             kaStarted.sendToTarget();
    658             Message kaRunning = mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STATUS);
    659             AsyncResult.forMessage(
    660                     kaRunning, new KeepaliveStatus(
    661                             sessionHandle, KeepaliveStatus.STATUS_ACTIVE), null);
    662             kaRunning.sendToTarget();
    663         }
    664         waitForMs(100);
    665 
    666         // Verify that we can stop the connection, which checks that the record in DataConnection
    667         // has a valid mapping between slotId (from network agent) to sessionHandle (from Radio).
    668         mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STOP_REQUEST, slotId).sendToTarget();
    669         waitForMs(100);
    670         verify(mSimulatedCommandsVerifier, times(1))
    671                 .stopNattKeepalive(eq(sessionHandle), any(Message.class));
    672 
    673         Message kaStopped = mDc.obtainMessage(
    674                 DataConnection.EVENT_KEEPALIVE_STOPPED, sessionHandle, slotId);
    675         AsyncResult.forMessage(kaStopped);
    676         kaStopped.sendToTarget();
    677         // Verify that after the connection is stopped, the mapping for a Keepalive Session is
    678         // removed. Thus, subsequent calls to stop the same keepalive are ignored.
    679         mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STOP_REQUEST, slotId).sendToTarget();
    680         waitForMs(100);
    681         // Check that the mock has not been called subsequent to the previous invocation
    682         // while avoiding the use of reset()
    683         verify(mSimulatedCommandsVerifier, times(1))
    684                 .stopNattKeepalive(anyInt(), any(Message.class));
    685     }
    686 
    687     @Test
    688     @MediumTest
    689     public void testStartStopNattKeepalive() throws Exception {
    690         checkStartStopNattKeepalive(false);
    691     }
    692 
    693     @Test
    694     @MediumTest
    695     public void testStartStopNattKeepaliveCondensed() throws Exception {
    696         checkStartStopNattKeepalive(true);
    697     }
    698 
    699     public void checkStartNattKeepaliveFail(boolean useCondensedFlow) throws Exception {
    700         testConnectEvent();
    701         waitForMs(200);
    702 
    703         final int sessionHandle = 0xF00;
    704         final int slotId = 3;
    705         final int interval = 10; // seconds
    706         // Construct a new KeepalivePacketData request as we would receive from a Network Agent,
    707         // and check that the packet is sent to the RIL.
    708         KeepalivePacketData kd = KeepalivePacketData.nattKeepalivePacket(
    709                 NetworkUtils.numericToInetAddress("1.2.3.4"),
    710                 1234,
    711                 NetworkUtils.numericToInetAddress("8.8.8.8"),
    712                 4500);
    713         mDc.obtainMessage(
    714                 DataConnection.EVENT_KEEPALIVE_START_REQUEST, slotId, interval, kd).sendToTarget();
    715         waitForMs(100);
    716         verify(mSimulatedCommandsVerifier, times(1))
    717                 .startNattKeepalive(anyInt(), eq(kd), eq(interval * 1000), any(Message.class));
    718 
    719         Message kaStarted = mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STARTED, slotId, 0);
    720         if (useCondensedFlow) {
    721             // Indicate in the response that the keepalive has failed.
    722             AsyncResult.forMessage(
    723                     kaStarted, new KeepaliveStatus(KeepaliveStatus.ERROR_UNSUPPORTED), null);
    724             kaStarted.sendToTarget();
    725         } else {
    726             // Indicate that the keepalive is queued, and then signal a failure from the modem
    727             // such that a pending keepalive fails to activate.
    728             AsyncResult.forMessage(
    729                     kaStarted, new KeepaliveStatus(
    730                             sessionHandle, KeepaliveStatus.STATUS_PENDING), null);
    731             kaStarted.sendToTarget();
    732             Message kaRunning = mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STATUS);
    733             AsyncResult.forMessage(
    734                     kaRunning, new KeepaliveStatus(
    735                             sessionHandle, KeepaliveStatus.STATUS_INACTIVE), null);
    736             kaRunning.sendToTarget();
    737         }
    738         waitForMs(100);
    739         // Verify that a failed connection request cannot be stopped due to no record in
    740         // the DataConnection.
    741         mDc.obtainMessage(DataConnection.EVENT_KEEPALIVE_STOP_REQUEST, slotId).sendToTarget();
    742         waitForMs(100);
    743         verify(mSimulatedCommandsVerifier, times(0))
    744                 .stopNattKeepalive(anyInt(), any(Message.class));
    745     }
    746 
    747     @Test
    748     @SmallTest
    749     public void testStartNattKeepaliveFail() throws Exception {
    750         checkStartNattKeepaliveFail(false);
    751     }
    752 
    753     @Test
    754     @SmallTest
    755     public void testStartNattKeepaliveFailCondensed() throws Exception {
    756         checkStartNattKeepaliveFail(true);
    757     }
    758 }
    759