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;
18
19import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
20import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
21import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
22
23import static org.junit.Assert.assertEquals;
24import static org.junit.Assert.assertFalse;
25import static org.junit.Assert.assertTrue;
26import static org.junit.Assert.fail;
27import static org.mockito.Matchers.anyLong;
28import static org.mockito.Matchers.nullable;
29import static org.mockito.Mockito.anyBoolean;
30import static org.mockito.Mockito.anyInt;
31import static org.mockito.Mockito.atLeast;
32import static org.mockito.Mockito.doReturn;
33import static org.mockito.Mockito.eq;
34import static org.mockito.Mockito.times;
35import static org.mockito.Mockito.verify;
36
37import android.app.Activity;
38import android.app.IApplicationThread;
39import android.content.IIntentReceiver;
40import android.content.Intent;
41import android.content.SharedPreferences;
42import android.os.AsyncResult;
43import android.os.Bundle;
44import android.os.Handler;
45import android.os.HandlerThread;
46import android.os.Message;
47import android.os.Process;
48import android.os.WorkSource;
49import android.preference.PreferenceManager;
50import android.support.test.filters.FlakyTest;
51import android.telephony.CarrierConfigManager;
52import android.telephony.CellLocation;
53import android.telephony.ServiceState;
54import android.telephony.SubscriptionManager;
55import android.telephony.cdma.CdmaCellLocation;
56import android.telephony.gsm.GsmCellLocation;
57import android.test.suitebuilder.annotation.SmallTest;
58
59import com.android.internal.telephony.test.SimulatedCommands;
60import com.android.internal.telephony.uicc.IccException;
61import com.android.internal.telephony.uicc.IccRecords;
62
63import org.junit.After;
64import org.junit.Before;
65import org.junit.Ignore;
66import org.junit.Test;
67import org.mockito.ArgumentCaptor;
68import org.mockito.Mock;
69
70import java.util.List;
71
72public class GsmCdmaPhoneTest extends TelephonyTest {
73    @Mock
74    private Handler mTestHandler;
75
76    //mPhoneUnderTest
77    private GsmCdmaPhone mPhoneUT;
78    private GsmCdmaPhoneTestHandler mGsmCdmaPhoneTestHandler;
79
80    private static final int EVENT_EMERGENCY_CALLBACK_MODE_EXIT = 1;
81    private static final int EVENT_EMERGENCY_CALL_TOGGLE = 2;
82
83    private class GsmCdmaPhoneTestHandler extends HandlerThread {
84
85        private GsmCdmaPhoneTestHandler(String name) {
86            super(name);
87        }
88
89        @Override
90        public void onLooperPrepared() {
91            mPhoneUT = new GsmCdmaPhone(mContext, mSimulatedCommands, mNotifier, true, 0,
92                    PhoneConstants.PHONE_TYPE_GSM, mTelephonyComponentFactory);
93            setReady(true);
94        }
95    }
96
97    private void switchToGsm() {
98        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
99        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
100                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
101        //wait for voice RAT to be updated
102        waitForMs(50);
103        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
104    }
105
106    private void switchToCdma() {
107        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
108        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
109                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_IS95A}, null)));
110        //wait for voice RAT to be updated
111        waitForMs(100);
112        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
113    }
114
115    @Before
116    public void setUp() throws Exception {
117        super.setUp(getClass().getSimpleName());
118
119        doReturn(false).when(mSST).isDeviceShuttingDown();
120
121        mGsmCdmaPhoneTestHandler = new GsmCdmaPhoneTestHandler(TAG);
122        mGsmCdmaPhoneTestHandler.start();
123        waitUntilReady();
124        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
125        verify(mUiccController).registerForIccChanged(eq(mPhoneUT), integerArgumentCaptor.capture(),
126                nullable(Object.class));
127        Message msg = Message.obtain();
128        msg.what = integerArgumentCaptor.getValue();
129        mPhoneUT.sendMessage(msg);
130        waitForMs(50);
131    }
132
133    @After
134    public void tearDown() throws Exception {
135        mPhoneUT.removeCallbacksAndMessages(null);
136        mPhoneUT = null;
137        mGsmCdmaPhoneTestHandler.quit();
138        super.tearDown();
139    }
140
141    @Test
142    @SmallTest
143    public void testPhoneTypeSwitch() {
144        assertTrue(mPhoneUT.isPhoneTypeGsm());
145        switchToCdma();
146        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
147    }
148
149    @Test
150    @SmallTest
151    public void testHandleActionCarrierConfigChanged() {
152        // set voice radio tech in RIL to 1xRTT. ACTION_CARRIER_CONFIG_CHANGED should trigger a
153        // query and change phone type
154        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
155        assertTrue(mPhoneUT.isPhoneTypeGsm());
156        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
157        mContext.sendBroadcast(intent);
158        waitForMs(50);
159        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
160    }
161
162    @Test
163    @SmallTest
164    public void testGetServiceState() {
165        ServiceState serviceState = new ServiceState();
166        mSST.mSS = serviceState;
167        assertEquals(serviceState, mPhoneUT.getServiceState());
168    }
169
170    @Test
171    @SmallTest
172    public void testGetCellLocation() {
173        // GSM
174        CellLocation cellLocation = new GsmCellLocation();
175        WorkSource workSource = new WorkSource(Process.myUid(),
176            mContext.getPackageName());
177        doReturn(cellLocation).when(mSST).getCellLocation(workSource);
178        assertEquals(cellLocation, mPhoneUT.getCellLocation(workSource));
179
180        // Switch to CDMA
181        switchToCdma();
182
183        CdmaCellLocation cdmaCellLocation = new CdmaCellLocation();
184        cdmaCellLocation.setCellLocationData(0, 0, 0, 0, 0);
185        mSST.mCellLoc = cdmaCellLocation;
186
187        /*
188        LOCATION_MODE is a special case in SettingsProvider. Adding the special handling in mock
189        content provider is probably not worth the effort; it will also tightly couple tests with
190        SettingsProvider implementation.
191        // LOCATION_MODE_ON
192        Settings.Secure.putInt(mContext.getContentResolver(),
193                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
194        waitForMs(50);
195        CdmaCellLocation actualCellLocation = (CdmaCellLocation) mPhoneUT.getCellLocation();
196        assertEquals(0, actualCellLocation.getBaseStationLatitude());
197        assertEquals(0, actualCellLocation.getBaseStationLongitude());
198
199        // LOCATION_MODE_OFF
200        Settings.Secure.putInt(TestApplication.getAppContext().getContentResolver(),
201                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
202        waitForMs(50);
203        */
204
205        CdmaCellLocation actualCellLocation =
206                (CdmaCellLocation) mPhoneUT.getCellLocation(workSource);
207        assertEquals(CdmaCellLocation.INVALID_LAT_LONG,
208                actualCellLocation.getBaseStationLatitude());
209        assertEquals(CdmaCellLocation.INVALID_LAT_LONG,
210                actualCellLocation.getBaseStationLongitude());
211    }
212
213    @Test
214    @SmallTest
215    public void testGetPhoneType() {
216        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
217
218        // Switch to CDMA
219        switchToCdma();
220
221        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
222    }
223
224    @Test
225    @SmallTest
226    public void testGetDataConnectionState() {
227        // There are several cases possible. Testing few of them for now.
228        // 1. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn != APN_TYPE_EMERGENCY
229        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST).getCurrentDataConnectionState();
230        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
231                PhoneConstants.APN_TYPE_ALL));
232
233        // 2. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY, apn
234        // not connected
235        doReturn(DctConstants.State.IDLE).when(mDcTracker).getState(
236                PhoneConstants.APN_TYPE_EMERGENCY);
237        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
238                PhoneConstants.APN_TYPE_EMERGENCY));
239
240        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
241        // APN is connected, callTracker state = idle
242        doReturn(DctConstants.State.CONNECTED).when(mDcTracker).getState(
243                PhoneConstants.APN_TYPE_EMERGENCY);
244        mCT.mState = PhoneConstants.State.IDLE;
245        assertEquals(PhoneConstants.DataState.CONNECTED, mPhoneUT.getDataConnectionState(
246                PhoneConstants.APN_TYPE_EMERGENCY));
247
248        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
249        // APN enabled and CONNECTED, callTracker state != idle, !isConcurrentVoiceAndDataAllowed
250        mCT.mState = PhoneConstants.State.RINGING;
251        doReturn(false).when(mSST).isConcurrentVoiceAndDataAllowed();
252        assertEquals(PhoneConstants.DataState.SUSPENDED, mPhoneUT.getDataConnectionState(
253                PhoneConstants.APN_TYPE_EMERGENCY));
254    }
255
256    @Test
257    @SmallTest
258    public void testHandleInCallMmiCommands() {
259        try {
260            // Switch to CDMA
261            switchToCdma();
262
263            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
264
265            // Switch to GSM
266            switchToGsm();
267
268            mCT.mForegroundCall = mGsmCdmaCall;
269            mCT.mBackgroundCall = mGsmCdmaCall;
270            mCT.mRingingCall = mGsmCdmaCall;
271            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
272
273            // !isInCall
274            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
275
276            // isInCall
277            doReturn(GsmCdmaCall.State.ACTIVE).when(mGsmCdmaCall).getState();
278            assertTrue(mPhoneUT.handleInCallMmiCommands("0"));
279
280            // empty dialString
281            assertFalse(mPhoneUT.handleInCallMmiCommands(""));
282            assertFalse(mPhoneUT.handleInCallMmiCommands(null));
283
284        } catch (Exception e) {
285            fail(e.toString());
286        }
287    }
288
289    @Test
290    @SmallTest
291    public void testDial() {
292        try {
293            mSST.mSS = mServiceState;
294            doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
295
296            mCT.mForegroundCall = mGsmCdmaCall;
297            mCT.mBackgroundCall = mGsmCdmaCall;
298            mCT.mRingingCall = mGsmCdmaCall;
299            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
300
301            Connection connection = mPhoneUT.dial("1234567890", 0);
302            verify(mCT).dial("1234567890", null, null);
303        } catch (CallStateException e) {
304            fail();
305        }
306    }
307
308    @Test
309    @SmallTest
310    public void testHandlePinMmi() {
311        assertFalse(mPhoneUT.handlePinMmi("1234567890"));
312    }
313
314    @Test
315    @SmallTest
316    public void testSendBurstDtmf() {
317        //Should do nothing for GSM
318        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
319        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
320                anyInt(), nullable(Message.class));
321
322        switchToCdma();
323        //invalid character
324        mPhoneUT.sendBurstDtmf("12345a67890", 0, 0, null);
325        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
326                anyInt(), nullable(Message.class));
327
328        //state IDLE
329        mCT.mState = PhoneConstants.State.IDLE;
330        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
331        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
332                anyInt(), nullable(Message.class));
333
334        //state RINGING
335        mCT.mState = PhoneConstants.State.RINGING;
336        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
337        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
338                anyInt(), nullable(Message.class));
339
340        mCT.mState = PhoneConstants.State.OFFHOOK;
341        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
342        verify(mSimulatedCommandsVerifier).sendBurstDtmf("1234567890", 0, 0, null);
343    }
344
345    @Test
346    @SmallTest
347    public void testVoiceMailNumberGsm() {
348        String voiceMailNumber = "1234567890";
349        // first test for GSM
350        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
351
352        // no resource or sharedPreference set -- should be null
353        assertEquals(null, mPhoneUT.getVoiceMailNumber());
354
355        // voicemail number from config
356        mContextFixture.getCarrierConfigBundle().
357                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
358        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
359
360        // voicemail number that is explicitly set
361        voiceMailNumber = "1234567891";
362        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
363        verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
364                nullable(Message.class));
365
366        doReturn(voiceMailNumber).when(mSimRecords).getVoiceMailNumber();
367        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
368    }
369
370    @Test
371    @SmallTest
372    public void testVoiceMailNumberCdma() {
373        switchToCdma();
374        String voiceMailNumber = "1234567890";
375
376        // no resource or sharedPreference set -- should be *86
377        assertEquals("*86", mPhoneUT.getVoiceMailNumber());
378
379        // config_telephony_use_own_number_for_voicemail
380        mContextFixture.putBooleanResource(
381                com.android.internal.R.bool.config_telephony_use_own_number_for_voicemail, true);
382        doReturn(voiceMailNumber).when(mSST).getMdnNumber();
383        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
384
385        // voicemail number from config
386        voiceMailNumber = "1234567891";
387        mContextFixture.getCarrierConfigBundle().
388                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
389        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
390
391        // voicemail number from sharedPreference
392        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
393        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
394        verify(mRuimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
395                messageArgumentCaptor.capture());
396
397        Message msg = messageArgumentCaptor.getValue();
398        AsyncResult.forMessage(msg).exception =
399                new IccException("setVoiceMailNumber not implemented");
400        msg.sendToTarget();
401        waitForMs(50);
402
403        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
404    }
405
406    @FlakyTest
407    @Test
408    @Ignore
409    public void testVoiceMailCount() {
410        // initial value
411        assertEquals(0, mPhoneUT.getVoiceMessageCount());
412
413        // old sharedPreference set (testing upgrade from M to N scenario)
414        SharedPreferences sharedPreferences =
415                PreferenceManager.getDefaultSharedPreferences(mContext);
416        SharedPreferences.Editor editor = sharedPreferences.edit();
417        String imsi = "1234567890";
418        editor.putString("vm_id_key", imsi);
419        editor.putInt("vm_count_key", 5);
420        editor.apply();
421        doReturn(imsi).when(mSimRecords).getIMSI();
422
423        // updateVoiceMail should read old shared pref and delete it and new sharedPref should be
424        // updated now
425        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
426        mPhoneUT.updateVoiceMail();
427        assertEquals(5, mPhoneUT.getVoiceMessageCount());
428        assertEquals(null, sharedPreferences.getString("vm_id_key", null));
429        assertEquals(5, sharedPreferences.getInt("vm_count_key" + mPhoneUT.getSubId(), 0));
430
431        // sim records return count as 0, that overrides shared preference
432        doReturn(0).when(mSimRecords).getVoiceMessageCount();
433        mPhoneUT.updateVoiceMail();
434        assertEquals(0, mPhoneUT.getVoiceMessageCount());
435
436        // sim records return count as -1
437        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
438        mPhoneUT.updateVoiceMail();
439        assertEquals(-1, mPhoneUT.getVoiceMessageCount());
440
441        // sim records return count as -1 and sharedPreference says 0
442        mPhoneUT.setVoiceMessageCount(0);
443        mPhoneUT.updateVoiceMail();
444        assertEquals(-1, mPhoneUT.getVoiceMessageCount());
445
446        // sim records return count as -1 and sharedPreference says 2
447        mPhoneUT.setVoiceMessageCount(2);
448        mPhoneUT.updateVoiceMail();
449        assertEquals(2, mPhoneUT.getVoiceMessageCount());
450
451        // sim records return count as 0 and sharedPreference says 2
452        doReturn(0).when(mSimRecords).getVoiceMessageCount();
453        mPhoneUT.setVoiceMessageCount(2);
454        mPhoneUT.updateVoiceMail();
455        assertEquals(0, mPhoneUT.getVoiceMessageCount());
456    }
457
458    @Test
459    @SmallTest
460    public void testGetCallForwardingOption() {
461        // invalid reason (-1)
462        mPhoneUT.getCallForwardingOption(-1, null);
463        verify(mSimulatedCommandsVerifier, times(0)).queryCallForwardStatus(
464                anyInt(), anyInt(), nullable(String.class), nullable(Message.class));
465
466        // valid reason
467        String imsi = "1234567890";
468        doReturn(imsi).when(mSimRecords).getIMSI();
469        mPhoneUT.getCallForwardingOption(CF_REASON_UNCONDITIONAL, null);
470        verify(mSimulatedCommandsVerifier).queryCallForwardStatus(
471                eq(CF_REASON_UNCONDITIONAL), anyInt(), nullable(String.class),
472                nullable(Message.class));
473        waitForMs(50);
474        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(),
475                nullable(String.class));
476
477        // should have updated shared preferences
478        SharedPreferences sharedPreferences = PreferenceManager.
479                getDefaultSharedPreferences(mContext);
480        assertEquals(IccRecords.CALL_FORWARDING_STATUS_DISABLED,
481                sharedPreferences.getInt(Phone.CF_STATUS + mPhoneUT.getSubId(),
482                        IccRecords.CALL_FORWARDING_STATUS_ENABLED));
483
484        // clean up
485        SharedPreferences.Editor editor = sharedPreferences.edit();
486        editor.remove(Phone.CF_STATUS + mPhoneUT.getSubId());
487        editor.apply();
488    }
489
490    @Test
491    @SmallTest
492    public void testSetCallForwardingOption() {
493        String cfNumber = "1234567890";
494
495        // invalid action
496        mPhoneUT.setCallForwardingOption(-1, CF_REASON_UNCONDITIONAL,
497                cfNumber, 0, null);
498        verify(mSimulatedCommandsVerifier, times(0)).setCallForward(anyInt(), anyInt(), anyInt(),
499                nullable(String.class), anyInt(), nullable(Message.class));
500
501        // valid action
502        mPhoneUT.setCallForwardingOption(CF_ACTION_ENABLE, CF_REASON_UNCONDITIONAL, cfNumber, 0,
503                null);
504        verify(mSimulatedCommandsVerifier).setCallForward(eq(CF_ACTION_ENABLE),
505                eq(CF_REASON_UNCONDITIONAL), anyInt(), eq(cfNumber), eq(0),
506                nullable(Message.class));
507        waitForMs(50);
508        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(), eq(cfNumber));
509    }
510
511    /**
512     * GsmCdmaPhone handles a lot of messages. This function verifies behavior for messages that are
513     * received when obj is created and that are received on phone type switch
514     */
515    @FlakyTest
516    @Test
517    @SmallTest
518    public void testHandleInitialMessages() {
519        // EVENT_RADIO_AVAILABLE
520        verify(mSimulatedCommandsVerifier).getBasebandVersion(nullable(Message.class));
521        verify(mSimulatedCommandsVerifier).getDeviceIdentity(nullable(Message.class));
522        verify(mSimulatedCommandsVerifier).getRadioCapability(nullable(Message.class));
523        // once as part of constructor, and once on radio available
524        verify(mSimulatedCommandsVerifier, times(2)).startLceService(anyInt(), anyBoolean(),
525                nullable(Message.class));
526
527        // EVENT_RADIO_ON
528        verify(mSimulatedCommandsVerifier).getVoiceRadioTechnology(nullable(Message.class));
529        verify(mSimulatedCommandsVerifier).setPreferredNetworkType(
530                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
531
532        // verify responses for above requests:
533        // baseband version
534        verify(mTelephonyManager).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
535                nullable(String.class));
536        // IMEI
537        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
538        // IMEISV
539        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
540        // radio capability
541        verify(mSimulatedCommandsVerifier).getNetworkSelectionMode(nullable(Message.class));
542
543        switchToCdma(); // this leads to eventRadioAvailable handling on cdma
544
545        // EVENT_RADIO_AVAILABLE
546        verify(mSimulatedCommandsVerifier, times(2)).getBasebandVersion(nullable(Message.class));
547        verify(mSimulatedCommandsVerifier, times(2)).getDeviceIdentity(nullable(Message.class));
548        verify(mSimulatedCommandsVerifier, times(3)).startLceService(anyInt(), anyBoolean(),
549                nullable(Message.class));
550
551        // EVENT_RADIO_ON
552        verify(mSimulatedCommandsVerifier, times(2)).getVoiceRadioTechnology(
553                nullable(Message.class));
554        // once on radio on, and once on get baseband version
555        verify(mSimulatedCommandsVerifier, times(3)).setPreferredNetworkType(
556                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
557
558        // verify responses for above requests:
559        // baseband version
560        verify(mTelephonyManager, times(2)).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
561                nullable(String.class));
562        // device identity
563        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
564        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
565        assertEquals(SimulatedCommands.FAKE_ESN, mPhoneUT.getEsn());
566        assertEquals(SimulatedCommands.FAKE_MEID, mPhoneUT.getMeid());
567    }
568
569    @Test
570    @SmallTest
571    public void testEmergencyCallbackMessages() {
572        verify(mSimulatedCommandsVerifier).setEmergencyCallbackMode(eq(mPhoneUT), anyInt(),
573                nullable(Object.class));
574        verify(mSimulatedCommandsVerifier).registerForExitEmergencyCallbackMode(eq(mPhoneUT),
575                anyInt(), nullable(Object.class));
576
577        // verify handling of emergency callback mode
578        mSimulatedCommands.notifyEmergencyCallbackMode();
579        waitForMs(50);
580
581        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
582        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
583        try {
584            verify(mIActivityManager, atLeast(1)).broadcastIntent(eq((IApplicationThread)null),
585                    intentArgumentCaptor.capture(),
586                    eq((String)null),
587                    eq((IIntentReceiver)null),
588                    eq(Activity.RESULT_OK),
589                    eq((String)null),
590                    eq((Bundle)null),
591                    eq((String[])null),
592                    anyInt(),
593                    eq((Bundle)null),
594                    eq(false),
595                    eq(true),
596                    anyInt());
597        } catch(Exception e) {
598            fail("Unexpected exception: " + e.getStackTrace());
599        }
600
601        Intent intent = intentArgumentCaptor.getValue();
602        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
603        assertEquals(true, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, false));
604
605        // verify that wakeLock is acquired in ECM
606        assertEquals(true, mPhoneUT.getWakeLock().isHeld());
607
608        mPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null);
609        mPhoneUT.registerForEmergencyCallToggle(mTestHandler, EVENT_EMERGENCY_CALL_TOGGLE, null);
610
611        // verify handling of emergency callback mode exit
612        mSimulatedCommands.notifyExitEmergencyCallbackMode();
613        waitForMs(50);
614
615        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
616        try {
617            verify(mIActivityManager, atLeast(2)).broadcastIntent(eq((IApplicationThread)null),
618                    intentArgumentCaptor.capture(),
619                    eq((String)null),
620                    eq((IIntentReceiver)null),
621                    eq(Activity.RESULT_OK),
622                    eq((String)null),
623                    eq((Bundle)null),
624                    eq((String[])null),
625                    anyInt(),
626                    eq((Bundle)null),
627                    eq(false),
628                    eq(true),
629                    anyInt());
630        } catch(Exception e) {
631            fail("Unexpected exception: " + e.getStackTrace());
632        }
633
634        intent = intentArgumentCaptor.getValue();
635        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
636        assertEquals(false, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, true));
637
638        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
639
640        // verify EcmExitRespRegistrant and mEmergencyCallToggledRegistrants are notified
641        verify(mTestHandler, times(2)).sendMessageAtTime(messageArgumentCaptor.capture(),
642                anyLong());
643        List<Message> msgList = messageArgumentCaptor.getAllValues();
644        assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, msgList.get(0).what);
645        assertEquals(EVENT_EMERGENCY_CALL_TOGGLE, msgList.get(1).what);
646
647        // verify setInternalDataEnabled
648        verify(mDcTracker).setInternalDataEnabled(true);
649
650        // verify wakeLock released
651        assertEquals(false, mPhoneUT.getWakeLock().isHeld());
652    }
653
654    @Test
655    @SmallTest
656    public void testCallForwardingIndicator() {
657        doReturn(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN).when(mSimRecords).
658                getVoiceCallForwardingFlag();
659
660        // invalid subId
661        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubscriptionController).
662                getSubIdUsingPhoneId(anyInt());
663        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
664
665        // valid subId, sharedPreference not present
666        int subId1 = 0;
667        int subId2 = 1;
668        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
669        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
670
671        // old sharedPreference present
672        String imsi = "1234";
673        doReturn(imsi).when(mSimRecords).getIMSI();
674        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
675        SharedPreferences.Editor editor = sp.edit();
676        editor.putString(Phone.CF_ID, imsi);
677        editor.putInt(Phone.CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
678        editor.apply();
679        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
680
681        // old sharedPreference should be removed now
682        assertEquals(null, sp.getString(Phone.CF_ID, null));
683        assertEquals(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN,
684                sp.getInt(Phone.CF_ID, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN));
685
686        // now verify value from new sharedPreference
687        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
688
689        // check for another subId
690        doReturn(subId2).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
691        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
692
693        // set value for the new subId in sharedPreference
694        editor.putInt(Phone.CF_STATUS + subId2, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
695        editor.apply();
696        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
697
698        // switching back to previous subId, stored value should still be available
699        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
700        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
701
702        // cleanup
703        editor.remove(Phone.CF_STATUS + subId1);
704        editor.remove(Phone.CF_STATUS + subId2);
705        editor.apply();
706    }
707
708    @Test
709    @SmallTest
710    public void testEriLoading() {
711        mPhoneUT.mEriManager = mEriManager;
712        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_CARRIER_CONFIG_CHANGED,
713                null));
714        waitForMs(100);
715        verify(mEriManager, times(1)).loadEriFile();
716    }
717}
718