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