DcTrackerTest.java revision 4c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3
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
17package com.android.internal.telephony.dataconnection;
18
19import android.app.AlarmManager;
20import android.app.PendingIntent;
21import android.content.ContentResolver;
22import android.content.Context;
23import android.content.Intent;
24import android.database.Cursor;
25import android.database.MatrixCursor;
26import android.net.LinkProperties;
27import android.net.NetworkCapabilities;
28import android.net.NetworkRequest;
29import android.net.Uri;
30import android.os.HandlerThread;
31import android.os.IBinder;
32import android.os.Message;
33import android.os.PersistableBundle;
34import android.provider.Settings;
35import android.provider.Telephony;
36import android.telephony.CarrierConfigManager;
37import android.telephony.ServiceState;
38import android.telephony.SubscriptionInfo;
39import android.telephony.SubscriptionManager;
40import android.test.mock.MockContentProvider;
41import android.test.mock.MockContentResolver;
42import android.test.suitebuilder.annotation.MediumTest;
43import android.util.LocalLog;
44
45import com.android.internal.telephony.DctConstants;
46import com.android.internal.telephony.ISub;
47import com.android.internal.telephony.Phone;
48import com.android.internal.telephony.PhoneConstants;
49import com.android.internal.telephony.TelephonyTest;
50import com.android.internal.telephony.TestApplication;
51import com.android.internal.telephony.dataconnection.DcTracker.DataAllowFailReason;
52
53import org.junit.After;
54import org.junit.Before;
55import org.junit.Test;
56import org.mockito.ArgumentCaptor;
57import org.mockito.Mock;
58import org.mockito.invocation.InvocationOnMock;
59import org.mockito.stubbing.Answer;
60
61import java.lang.reflect.Method;
62import java.util.Arrays;
63import java.util.List;
64import java.util.regex.Matcher;
65import java.util.regex.Pattern;
66
67import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
68import static org.junit.Assert.assertArrayEquals;
69import static org.junit.Assert.assertEquals;
70import static org.junit.Assert.assertFalse;
71import static org.junit.Assert.assertTrue;
72import static org.junit.Assert.fail;
73import static org.mockito.Matchers.any;
74import static org.mockito.Matchers.anyInt;
75import static org.mockito.Matchers.anyLong;
76import static org.mockito.Matchers.anyString;
77import static org.mockito.Matchers.eq;
78import static org.mockito.Mockito.doReturn;
79import static org.mockito.Mockito.doAnswer;
80import static org.mockito.Mockito.never;
81import static org.mockito.Mockito.times;
82import static org.mockito.Mockito.verify;
83
84public class DcTrackerTest extends TelephonyTest {
85
86    private final static String[] sNetworkAttributes = new String[]{
87            "mobile,0,0,0,-1,true", "mobile_mms,2,0,2,60000,true",
88            "mobile_supl,3,0,2,60000,true", "mobile_dun,4,0,2,60000,true",
89            "mobile_hipri,5,0,3,60000,true", "mobile_fota,10,0,2,60000,true",
90            "mobile_ims,11,0,2,60000,true", "mobile_cbs,12,0,2,60000,true",
91            "mobile_ia,14,0,2,-1,true", "mobile_emergency,15,0,2,-1,true"};
92
93    private final static List<String> sApnTypes = Arrays.asList(
94            "default", "mms", "cbs", "fota", "supl", "ia", "emergency", "dun", "hipri", "ims");
95
96    private static final String FAKE_APN1 = "FAKE APN 1";
97    private static final String FAKE_APN2 = "FAKE APN 2";
98    private static final String FAKE_APN3 = "FAKE APN 3";
99    private static final String FAKE_IFNAME = "FAKE IFNAME";
100    private static final String FAKE_PCSCF_ADDRESS = "22.33.44.55";
101    private static final String FAKE_GATEWAY = "11.22.33.44";
102    private static final String FAKE_DNS = "55.66.77.88";
103    private static final String FAKE_ADDRESS = "99.88.77.66";
104
105    @Mock
106    ISub mIsub;
107    @Mock
108    IBinder mBinder;
109    @Mock
110    NetworkRequest mNetworkRequest;
111    @Mock
112    SubscriptionInfo mSubscriptionInfo;
113
114    private DcTracker mDct;
115
116    private AlarmManager mAlarmManager;
117
118    private PersistableBundle mBundle;
119
120    private SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
121
122    private final ApnSettingContentProvider mApnSettingContentProvider =
123            new ApnSettingContentProvider();
124
125    private class DcTrackerTestHandler extends HandlerThread {
126
127        private DcTrackerTestHandler(String name) {
128            super(name);
129        }
130
131        @Override
132        public void onLooperPrepared() {
133            mDct = new DcTracker(mPhone);
134            setReady(true);
135        }
136    }
137
138    private class ApnSettingContentProvider extends MockContentProvider {
139
140        @Override
141        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
142                            String sortOrder) {
143            logd("ApnSettingContentProvider: query");
144            logd("   uri = " + uri);
145            logd("   projection = " + Arrays.toString(projection));
146            logd("   selection = " + selection);
147            logd("   selectionArgs = " + Arrays.toString(selectionArgs));
148            logd("   sortOrder = " + sortOrder);
149
150            if (uri.compareTo(Telephony.Carriers.CONTENT_URI) == 0) {
151                if (projection == null && selectionArgs == null && selection != null) {
152
153                    Pattern pattern = Pattern.compile("^numeric = '([0-9]*)'");
154                    Matcher matcher = pattern.matcher(selection);
155                    if (!matcher.find()) {
156                        logd("Cannot find MCC/MNC from " + selection);
157                        return null;
158                    }
159
160                    String plmn = matcher.group(1);
161
162                    logd("Query '" + plmn + "' APN settings");
163                    MatrixCursor mc = new MatrixCursor(
164                            new String[]{Telephony.Carriers._ID, Telephony.Carriers.NUMERIC,
165                                    Telephony.Carriers.NAME, Telephony.Carriers.APN,
166                                    Telephony.Carriers.PROXY, Telephony.Carriers.PORT,
167                                    Telephony.Carriers.MMSC, Telephony.Carriers.MMSPROXY,
168                                    Telephony.Carriers.MMSPORT, Telephony.Carriers.USER,
169                                    Telephony.Carriers.PASSWORD, Telephony.Carriers.AUTH_TYPE,
170                                    Telephony.Carriers.TYPE,
171                                    Telephony.Carriers.PROTOCOL,
172                                    Telephony.Carriers.ROAMING_PROTOCOL,
173                                    Telephony.Carriers.CARRIER_ENABLED, Telephony.Carriers.BEARER,
174                                    Telephony.Carriers.BEARER_BITMASK,
175                                    Telephony.Carriers.PROFILE_ID,
176                                    Telephony.Carriers.MODEM_COGNITIVE,
177                                    Telephony.Carriers.MAX_CONNS, Telephony.Carriers.WAIT_TIME,
178                                    Telephony.Carriers.MAX_CONNS_TIME, Telephony.Carriers.MTU,
179                                    Telephony.Carriers.MVNO_TYPE,
180                                    Telephony.Carriers.MVNO_MATCH_DATA});
181
182                    mc.addRow(new Object[]{
183                            2163,                   // id
184                            plmn,                   // numeric
185                            "sp-mode",              // name
186                            FAKE_APN1,              // apn
187                            "",                     // proxy
188                            "",                     // port
189                            "",                     // mmsc
190                            "",                     // mmsproxy
191                            "",                     // mmsport
192                            "",                     // user
193                            "",                     // password
194                            -1,                     // authtype
195                            "default,supl",         // types
196                            "IP",                   // protocol
197                            "IP",                   // roaming_protocol
198                            1,                      // carrier_enabled
199                            0,                      // bearer
200                            0,                      // bearer_bitmask
201                            0,                      // profile_id
202                            0,                      // modem_cognitive
203                            0,                      // max_conns
204                            0,                      // wait_time
205                            0,                      // max_conns_time
206                            0,                      // mtu
207                            "",                     // mvno_type
208                            ""                      // mnvo_match_data
209                    });
210
211                    mc.addRow(new Object[]{
212                            2164,                   // id
213                            plmn,                   // numeric
214                            "mopera U",             // name
215                            FAKE_APN2,              // apn
216                            "",                     // proxy
217                            "",                     // port
218                            "",                     // mmsc
219                            "",                     // mmsproxy
220                            "",                     // mmsport
221                            "",                     // user
222                            "",                     // password
223                            -1,                     // authtype
224                            "default,supl",         // types
225                            "IP",                   // protocol
226                            "IP",                   // roaming_protocol
227                            1,                      // carrier_enabled
228                            0,                      // bearer
229                            0,                      // bearer_bitmask
230                            0,                      // profile_id
231                            0,                      // modem_cognitive
232                            0,                      // max_conns
233                            0,                      // wait_time
234                            0,                      // max_conns_time
235                            0,                      // mtu
236                            "",                     // mvno_type
237                            ""                      // mnvo_match_data
238                    });
239
240                    mc.addRow(new Object[]{
241                            2165,                   // id
242                            plmn,                   // numeric
243                            "b-mobile for Nexus",   // name
244                            FAKE_APN3,              // apn
245                            "",                     // proxy
246                            "",                     // port
247                            "",                     // mmsc
248                            "",                     // mmsproxy
249                            "",                     // mmsport
250                            "",                     // user
251                            "",                     // password
252                            3,                      // authtype
253                            "ims",                  // types
254                            "IP",                   // protocol
255                            "IP",                   // roaming_protocol
256                            1,                      // carrier_enabled
257                            0,                      // bearer
258                            0,                      // bearer_bitmask
259                            0,                      // profile_id
260                            0,                      // modem_cognitive
261                            0,                      // max_conns
262                            0,                      // wait_time
263                            0,                      // max_conns_time
264                            0,                      // mtu
265                            "",                     // mvno_type
266                            ""                      // mnvo_match_data
267                    });
268
269                    return mc;
270                }
271            }
272
273            return null;
274        }
275    }
276
277    @Before
278    public void setUp() throws Exception {
279        // set the lazy cp to the real content provider in order to use the real settings
280        ContentResolver realContentResolver = TestApplication.getAppContext().getContentResolver();
281        Settings.Global.getInt(realContentResolver, Settings.Global.MOBILE_DATA, 1);
282
283        logd("DcTrackerTest +Setup!");
284        super.setUp(getClass().getSimpleName());
285
286        doReturn("fake.action_detached").when(mPhone).getActionDetached();
287        doReturn("fake.action_attached").when(mPhone).getActionAttached();
288        doReturn("44010").when(mSimRecords).getOperatorNumeric();
289
290        mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
291                sNetworkAttributes);
292        mContextFixture.putStringArrayResource(com.android.internal.R.array.
293                config_mobile_tcp_buffers, new String[]{
294                "umts:131072,262144,1452032,4096,16384,399360",
295                "hspa:131072,262144,2441216,4096,16384,399360",
296                "hsupa:131072,262144,2441216,4096,16384,399360",
297                "hsdpa:131072,262144,2441216,4096,16384,399360",
298                "hspap:131072,262144,2441216,4096,16384,399360",
299                "edge:16384,32768,131072,4096,16384,65536",
300                "gprs:4096,8192,24576,4096,8192,24576",
301                "1xrtt:16384,32768,131070,4096,16384,102400",
302                "evdo:131072,262144,1048576,4096,16384,524288",
303                "lte:524288,1048576,8388608,262144,524288,4194304"});
304
305        ((MockContentResolver) mContext.getContentResolver()).addProvider(
306                Telephony.Carriers.CONTENT_URI.getAuthority(), mApnSettingContentProvider);
307
308        doReturn(true).when(mSimRecords).getRecordsLoaded();
309        doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
310        doReturn(true).when(mSST).getDesiredPowerState();
311        doAnswer(
312                new Answer<Void>() {
313                    @Override
314                    public Void answer(InvocationOnMock invocation) throws Throwable {
315                        mOnSubscriptionsChangedListener =
316                                (SubscriptionManager.OnSubscriptionsChangedListener)
317                                        invocation.getArguments()[0];
318                        return null;
319                    }
320                }
321        ).when(mSubscriptionManager).addOnSubscriptionsChangedListener(any());
322        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
323
324        doReturn(1).when(mIsub).getDefaultDataSubId();
325        doReturn(mIsub).when(mBinder).queryLocalInterface(anyString());
326        mServiceManagerMockedServices.put("isub", mBinder);
327
328        mContextFixture.putStringArrayResource(
329                com.android.internal.R.array.config_cell_retries_per_error_code,
330                new String[]{"36,2"});
331
332        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
333        mBundle = mContextFixture.getCarrierConfigBundle();
334
335        new DcTrackerTestHandler(getClass().getSimpleName()).start();
336        waitUntilReady();
337        waitForMs(600);
338        logd("DcTrackerTest -Setup!");
339    }
340
341    @After
342    public void tearDown() throws Exception {
343        logd("DcTrackerTest -tearDown");
344        mDct.removeCallbacksAndMessages(null);
345        mDct = null;
346        super.tearDown();
347    }
348
349    // Create a successful data response
350    public static DataCallResponse createDataCallResponse() {
351
352        DataCallResponse dcResponse = new DataCallResponse();
353
354        dcResponse.version = 11;
355        dcResponse.status = 0;
356        dcResponse.suggestedRetryTime = -1; // No retry suggested by the modem
357        dcResponse.cid = 1;
358        dcResponse.active = 2;
359        dcResponse.type = "IP";
360        dcResponse.ifname = FAKE_IFNAME;
361        dcResponse.mtu = 1440;
362        dcResponse.addresses = new String[]{FAKE_ADDRESS};
363        dcResponse.dnses = new String[]{FAKE_DNS};
364        dcResponse.gateways = new String[]{FAKE_GATEWAY};
365        dcResponse.pcscf = new String[]{FAKE_PCSCF_ADDRESS};
366        return dcResponse;
367    }
368
369    private void verifyDataConnected(final String apnSetting) {
370        verify(mPhone, times(1)).notifyDataConnection(eq(Phone.REASON_CONNECTED),
371                eq(PhoneConstants.APN_TYPE_DEFAULT));
372
373        verify(mAlarmManager, times(1)).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(),
374                any(PendingIntent.class));
375
376        assertEquals(apnSetting, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
377        assertArrayEquals(new String[]{PhoneConstants.APN_TYPE_DEFAULT}, mDct.getActiveApnTypes());
378        assertTrue(mDct.getAnyDataEnabled());
379
380        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
381        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
382
383        LinkProperties linkProperties = mDct.getLinkProperties(PhoneConstants.APN_TYPE_DEFAULT);
384        assertEquals(FAKE_IFNAME, linkProperties.getInterfaceName());
385        assertEquals(1, linkProperties.getAddresses().size());
386        assertEquals(FAKE_ADDRESS, linkProperties.getAddresses().get(0).getHostAddress());
387        assertEquals(1, linkProperties.getDnsServers().size());
388        assertEquals(FAKE_DNS, linkProperties.getDnsServers().get(0).getHostAddress());
389        assertEquals(FAKE_GATEWAY, linkProperties.getRoutes().get(0).getGateway().getHostAddress());
390    }
391
392    private boolean isDataAllowed(DataAllowFailReason dataAllowFailReasons) {
393        try {
394            Method method = DcTracker.class.getDeclaredMethod("isDataAllowed",
395                    DataAllowFailReason.class);
396            method.setAccessible(true);
397            return (boolean) method.invoke(mDct, dataAllowFailReasons);
398        } catch (Exception e) {
399            fail(e.toString());
400            return false;
401        }
402    }
403
404    // Test the normal data call setup scenario.
405    @Test
406    @MediumTest
407    public void testDataSetup() {
408
409        mDct.setDataEnabled(true);
410
411        mSimulatedCommands.setDataCallResponse(true, createDataCallResponse());
412
413        DataAllowFailReason failureReason = new DataAllowFailReason();
414        boolean allowed = isDataAllowed(failureReason);
415        assertFalse(failureReason.getDataAllowFailReason(), allowed);
416
417        logd("Sending EVENT_RECORDS_LOADED");
418        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
419        waitForMs(200);
420
421        ArgumentCaptor<String> apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
422        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
423                eq(Phone.REASON_SIM_LOADED), apnTypeArgumentCaptor.capture(),
424                eq(PhoneConstants.DataState.DISCONNECTED));
425
426        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
427
428        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
429        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
430        waitForMs(200);
431
432        apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
433        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
434                eq(Phone.REASON_DATA_ATTACHED), apnTypeArgumentCaptor.capture(),
435                eq(PhoneConstants.DataState.DISCONNECTED));
436
437        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
438
439        apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
440        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
441                eq(Phone.REASON_DATA_ENABLED), apnTypeArgumentCaptor.capture(),
442                eq(PhoneConstants.DataState.DISCONNECTED));
443
444        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
445
446        logd("Sending EVENT_ENABLE_NEW_APN");
447        // APN id 0 is APN_TYPE_DEFAULT
448        mDct.setEnabled(0, true);
449        waitForMs(200);
450
451        failureReason.clearAllReasons();
452        allowed = isDataAllowed(failureReason);
453        assertTrue(failureReason.getDataAllowFailReason(), allowed);
454
455        // Verify if RIL command was sent properly.
456        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
457                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
458                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
459
460        verifyDataConnected(FAKE_APN1);
461    }
462
463    // Test the scenario where the first data call setup is failed, and then retry the setup later.
464    @Test
465    @MediumTest
466    public void testDataRetry() {
467
468        mDct.setDataEnabled(true);
469
470        DataCallResponse dcResponse = createDataCallResponse();
471        // LOST_CONNECTION(0x10004) is a non-permanent failure, so we'll retry data setup later.
472        dcResponse.status = 0x10004;
473        // Simulate RIL fails the data call setup
474        mSimulatedCommands.setDataCallResponse(false, dcResponse);
475
476        DataAllowFailReason failureReason = new DataAllowFailReason();
477        boolean allowed = isDataAllowed(failureReason);
478        assertFalse(failureReason.getDataAllowFailReason(), allowed);
479
480        logd("Sending EVENT_RECORDS_LOADED");
481        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
482        waitForMs(200);
483
484        ArgumentCaptor<String> apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
485        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
486                eq(Phone.REASON_SIM_LOADED), apnTypeArgumentCaptor.capture(),
487                eq(PhoneConstants.DataState.DISCONNECTED));
488
489        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
490
491        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
492        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
493        waitForMs(200);
494
495        apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
496        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
497                eq(Phone.REASON_DATA_ATTACHED), apnTypeArgumentCaptor.capture(),
498                eq(PhoneConstants.DataState.DISCONNECTED));
499
500        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
501
502        apnTypeArgumentCaptor = ArgumentCaptor.forClass(String.class);
503        verify(mPhone, times(sNetworkAttributes.length)).notifyDataConnection(
504                eq(Phone.REASON_DATA_ENABLED), apnTypeArgumentCaptor.capture(),
505                eq(PhoneConstants.DataState.DISCONNECTED));
506
507        assertEquals(sApnTypes, apnTypeArgumentCaptor.getAllValues());
508
509        logd("Sending EVENT_ENABLE_NEW_APN");
510        // APN id 0 is APN_TYPE_DEFAULT
511        mDct.setEnabled(0, true);
512        waitForMs(200);
513
514
515        failureReason.clearAllReasons();
516        allowed = isDataAllowed(failureReason);
517        assertTrue(failureReason.getDataAllowFailReason(), allowed);
518
519        // Verify if RIL command was sent properly.
520        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
521                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
522                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
523
524        // Make sure we never notify connected because the data call setup is supposed to fail.
525        verify(mPhone, never()).notifyDataConnection(eq(Phone.REASON_CONNECTED),
526                eq(PhoneConstants.APN_TYPE_DEFAULT));
527
528        // Verify the retry manger schedule another data call setup.
529        verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
530                anyLong(), any(PendingIntent.class));
531
532        // This time we'll let RIL command succeed.
533        mSimulatedCommands.setDataCallResponse(true, createDataCallResponse());
534
535        // Simulate the timer expires.
536        Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
537        intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
538        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
539        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
540        mContext.sendBroadcast(intent);
541        waitForMs(200);
542
543        // Verify if RIL command was sent properly.
544        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
545                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN2),
546                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
547
548        // Verify connected with APN2 setting.
549        verifyDataConnected(FAKE_APN2);
550    }
551
552    @Test
553    @MediumTest
554    public void testUserDisableData() throws Exception {
555        //step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
556        //set Default and MMS to be metered in the CarrierConfigManager
557        boolean dataEnabled = mDct.getDataEnabled();
558        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
559                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
560        mDct.setEnabled(5, true);
561        mDct.setEnabled(0, true);
562
563        logd("Sending EVENT_RECORDS_LOADED");
564        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
565        waitForMs(200);
566
567        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
568        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
569        waitForMs(200);
570
571        logd("Sending DATA_ENABLED_CMD");
572        mDct.setDataEnabled(true);
573
574        waitForMs(200);
575        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
576                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
577                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
578        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
579                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
580                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));
581
582        logd("Sending DATA_DISABLED_CMD");
583        mDct.setDataEnabled(false);
584        waitForMs(200);
585
586        // expected tear down all metered DataConnections
587        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
588                any(Message.class));
589        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
590        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
591        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
592
593        // reset the setting at the end of this test
594        mDct.setDataEnabled(dataEnabled);
595        waitForMs(200);
596    }
597
598    @Test
599    @MediumTest
600    public void testUserDisableRoaming() throws Exception {
601        //step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
602        //step 2: set roaming disabled, data is enabled
603        //step 3: under roaming service
604        //step 4: only tear down metered data connections.
605
606        //set Default and MMS to be metered in the CarrierConfigManager
607        boolean roamingEnabled = mDct.getDataOnRoamingEnabled();
608        boolean dataEnabled = mDct.getDataEnabled();
609
610        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
611                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
612        mDct.setEnabled(5, true);
613        mDct.setEnabled(0, true);
614
615        logd("Sending EVENT_RECORDS_LOADED");
616        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
617        waitForMs(200);
618
619        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
620        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
621        waitForMs(200);
622
623        logd("Sending DATA_ENABLED_CMD");
624        mDct.setDataEnabled(true);
625
626        waitForMs(200);
627        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
628                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
629                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
630        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
631                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
632                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));
633
634        //user is in roaming
635        doReturn(true).when(mServiceState).getDataRoaming();
636        logd("Sending DISABLE_ROAMING_CMD");
637        mDct.setDataOnRoamingEnabled(false);
638        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_ROAMING_ON));
639        waitForMs(200);
640
641        // expected tear down all metered DataConnections
642        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
643                any(Message.class));
644        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
645        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
646        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
647
648        // reset roaming settings / data enabled settings at end of this test
649        mDct.setDataOnRoamingEnabled(roamingEnabled);
650        mDct.setDataEnabled(dataEnabled);
651        waitForMs(200);
652    }
653
654    @Test
655    @MediumTest
656    public void testDataCallOnUserDisableRoaming() throws Exception {
657        //step 1: mock under roaming service and user disabled roaming from settings.
658        //step 2: user toggled data settings on
659        //step 3: only non-metered data call is established
660
661        boolean roamingEnabled = mDct.getDataOnRoamingEnabled();
662        boolean dataEnabled = mDct.getDataEnabled();
663
664        //set Default and MMS to be metered in the CarrierConfigManager
665        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
666                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
667        mDct.setEnabled(5, true);
668        mDct.setEnabled(0, true);
669        doReturn(true).when(mServiceState).getDataRoaming();
670
671        logd("Sending DISABLE_ROAMING_CMD");
672        mDct.setDataOnRoamingEnabled(false);
673
674        logd("Sending EVENT_RECORDS_LOADED");
675        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
676        waitForMs(200);
677
678        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
679        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
680        waitForMs(200);
681
682        logd("Sending DATA_ENABLED_CMD");
683        mDct.setDataEnabled(true);
684
685        waitForMs(200);
686        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
687                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
688                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
689        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
690                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
691                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));
692
693        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
694        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
695        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
696
697        // reset roaming settings / data enabled settings at end of this test
698        mDct.setDataOnRoamingEnabled(roamingEnabled);
699        mDct.setDataEnabled(dataEnabled);
700        waitForMs(200);
701    }
702
703    // Test the default data switch scenario.
704    @Test
705    @MediumTest
706    public void testDDSResetAutoAttach() throws Exception {
707
708        mDct.setDataEnabled(true);
709
710        mContextFixture.putBooleanResource(
711                com.android.internal.R.bool.config_auto_attach_data_on_creation, true);
712
713        mSimulatedCommands.setDataCallResponse(true, createDataCallResponse());
714
715        DataAllowFailReason failureReason = new DataAllowFailReason();
716        boolean allowed = isDataAllowed(failureReason);
717        assertFalse(failureReason.getDataAllowFailReason(), allowed);
718
719        ArgumentCaptor<Integer> intArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
720        verify(mUiccController, times(1)).registerForIccChanged(eq(mDct),
721                intArgumentCaptor.capture(), eq(null));
722        // Ideally this should send EVENT_ICC_CHANGED.
723        mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
724        waitForMs(100);
725
726        verify(mSimRecords, times(1)).registerForRecordsLoaded(eq(mDct),
727                intArgumentCaptor.capture(), eq(null));
728        // Ideally this should send EVENT_RECORDS_LOADED.
729        mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
730        waitForMs(100);
731
732        verify(mSST, times(1)).registerForDataConnectionAttached(eq(mDct),
733                intArgumentCaptor.capture(), eq(null));
734        // Ideally this should send EVENT_DATA_CONNECTION_ATTACHED");
735        mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
736        waitForMs(200);
737
738        NetworkCapabilities nc = new NetworkCapabilities();
739        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
740        NetworkRequest nr = new NetworkRequest(nc, 0, 0);
741        LocalLog l = new LocalLog(100);
742        mDct.requestNetwork(nr, l);
743        waitForMs(200);
744
745        verifyDataConnected(FAKE_APN1);
746
747        assertTrue(mDct.getAutoAttachOnCreation());
748        mDct.update();
749        // The auto attach flag should be reset after update
750        assertFalse(mDct.getAutoAttachOnCreation());
751
752        verify(mSST, times(1)).registerForDataConnectionDetached(eq(mDct),
753                intArgumentCaptor.capture(), eq(null));
754        // Ideally this should send EVENT_DATA_CONNECTION_DETACHED
755        mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
756        waitForMs(200);
757
758        // Data should not be allowed since auto attach flag has been reset.
759        failureReason.clearAllReasons();
760        allowed = isDataAllowed(failureReason);
761        assertFalse(failureReason.getDataAllowFailReason(), allowed);
762    }
763
764    // Test for API carrierActionSetMeteredApnsEnabled.
765    @Test
766    @MediumTest
767    public void testCarrierActionSetMeteredApnsEnabled() throws Exception {
768        //step 1: setup two DataCalls one for Internet and IMS
769        //step 2: set data is enabled
770        //step 3: cold sim is detected
771        //step 4: all data connection is torn down
772        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
773                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
774
775        boolean dataEnabled = mDct.getDataEnabled();
776        mDct.setDataEnabled(true);
777
778        mDct.setEnabled(5, true);
779        mDct.setEnabled(0, true);
780
781        logd("Sending EVENT_RECORDS_LOADED");
782        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
783        waitForMs(200);
784
785        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
786        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
787        waitForMs(200);
788
789        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
790                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
791                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));
792        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
793                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
794                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
795        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
796
797        mDct.carrierActionSetMeteredApnsEnabled(false);
798        waitForMs(100);
799
800        // Validate all metered data connections have been torn down
801        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
802                any(Message.class));
803        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
804        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
805
806        // Reset settings at the end of test
807        mDct.setDataEnabled(dataEnabled);
808        waitForMs(200);
809    }
810}
811