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.mock;
35import static org.mockito.Mockito.spy;
36import static org.mockito.Mockito.times;
37import static org.mockito.Mockito.verify;
38
39import android.app.Activity;
40import android.app.IApplicationThread;
41import android.content.IIntentReceiver;
42import android.content.Intent;
43import android.content.SharedPreferences;
44import android.os.AsyncResult;
45import android.os.Bundle;
46import android.os.Handler;
47import android.os.HandlerThread;
48import android.os.Message;
49import android.os.Process;
50import android.os.WorkSource;
51import android.preference.PreferenceManager;
52import android.support.test.filters.FlakyTest;
53import android.telephony.CarrierConfigManager;
54import android.telephony.CellLocation;
55import android.telephony.ServiceState;
56import android.telephony.SubscriptionManager;
57import android.telephony.cdma.CdmaCellLocation;
58import android.telephony.gsm.GsmCellLocation;
59import android.test.suitebuilder.annotation.SmallTest;
60
61import com.android.internal.telephony.test.SimulatedCommands;
62import com.android.internal.telephony.uicc.IccCardApplicationStatus;
63import com.android.internal.telephony.uicc.IccException;
64import com.android.internal.telephony.uicc.IccRecords;
65import com.android.internal.telephony.uicc.UiccController;
66import com.android.internal.telephony.uicc.UiccProfile;
67import com.android.internal.telephony.uicc.UiccSlot;
68
69import org.junit.After;
70import org.junit.Before;
71import org.junit.Ignore;
72import org.junit.Test;
73import org.mockito.ArgumentCaptor;
74import org.mockito.Mock;
75import org.mockito.Mockito;
76
77import java.util.List;
78
79public class GsmCdmaPhoneTest extends TelephonyTest {
80    @Mock
81    private Handler mTestHandler;
82
83    //mPhoneUnderTest
84    private GsmCdmaPhone mPhoneUT;
85    private GsmCdmaPhoneTestHandler mGsmCdmaPhoneTestHandler;
86
87    private static final int EVENT_EMERGENCY_CALLBACK_MODE_EXIT = 1;
88    private static final int EVENT_EMERGENCY_CALL_TOGGLE = 2;
89    private static final int EVENT_SET_ICC_LOCK_ENABLED = 3;
90
91    private class GsmCdmaPhoneTestHandler extends HandlerThread {
92
93        private GsmCdmaPhoneTestHandler(String name) {
94            super(name);
95        }
96
97        @Override
98        public void onLooperPrepared() {
99            mPhoneUT = new GsmCdmaPhone(mContext, mSimulatedCommands, mNotifier, true, 0,
100                    PhoneConstants.PHONE_TYPE_GSM, mTelephonyComponentFactory);
101            setReady(true);
102        }
103    }
104
105    private void switchToGsm() {
106        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
107        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
108                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
109        //wait for voice RAT to be updated
110        waitForMs(50);
111        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
112    }
113
114    private void switchToCdma() {
115        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
116        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
117                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_IS95A}, null)));
118        //wait for voice RAT to be updated
119        waitForMs(100);
120        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
121    }
122
123    @Before
124    public void setUp() throws Exception {
125        super.setUp(getClass().getSimpleName());
126
127        doReturn(false).when(mSST).isDeviceShuttingDown();
128
129        mGsmCdmaPhoneTestHandler = new GsmCdmaPhoneTestHandler(TAG);
130        mGsmCdmaPhoneTestHandler.start();
131        waitUntilReady();
132        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
133        verify(mUiccController).registerForIccChanged(eq(mPhoneUT), integerArgumentCaptor.capture(),
134                nullable(Object.class));
135        Message msg = Message.obtain();
136        msg.what = integerArgumentCaptor.getValue();
137        mPhoneUT.sendMessage(msg);
138        waitForMs(50);
139    }
140
141    @After
142    public void tearDown() throws Exception {
143        mPhoneUT.removeCallbacksAndMessages(null);
144        mPhoneUT = null;
145        mGsmCdmaPhoneTestHandler.quit();
146        super.tearDown();
147    }
148
149    @Test
150    @SmallTest
151    public void testPhoneTypeSwitch() {
152        assertTrue(mPhoneUT.isPhoneTypeGsm());
153        switchToCdma();
154        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
155    }
156
157    @Test
158    @SmallTest
159    public void testHandleActionCarrierConfigChanged() {
160        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
161        mContext.sendBroadcast(intent);
162        waitForMs(50);
163        verify(mSST, times(1)).pollState();
164
165        // set voice radio tech in RIL to 1xRTT. ACTION_CARRIER_CONFIG_CHANGED should trigger a
166        // query and change phone type
167        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
168        assertTrue(mPhoneUT.isPhoneTypeGsm());
169        mContext.sendBroadcast(intent);
170        waitForMs(50);
171        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
172        verify(mSST, times(2)).pollState();
173    }
174
175    @Test
176    @SmallTest
177    public void testGetServiceState() {
178        ServiceState serviceState = new ServiceState();
179        mSST.mSS = serviceState;
180        assertEquals(serviceState, mPhoneUT.getServiceState());
181    }
182
183    @Test
184    @SmallTest
185    public void testGetSubscriberIdForGsmPhone() {
186        final String subscriberId = "123456789";
187        IccRecords iccRecords = Mockito.mock(IccRecords.class);
188        doReturn(subscriberId).when(iccRecords).getIMSI();
189        doReturn(iccRecords).when(mUiccController)
190                .getIccRecords(anyInt() /* phoneId */, eq(UiccController.APP_FAM_3GPP));
191
192        // Ensure the phone type is GSM
193        GsmCdmaPhone spyPhone = spy(mPhoneUT);
194        doReturn(false).when(spyPhone).isPhoneTypeCdma();
195        doReturn(false).when(spyPhone).isPhoneTypeCdmaLte();
196        doReturn(true).when(spyPhone).isPhoneTypeGsm();
197
198        assertEquals(subscriberId, spyPhone.getSubscriberId());
199    }
200
201    @Test
202    @SmallTest
203    public void testGetSubscriberIdForCdmaLtePhone() {
204        final String subscriberId = "abcdefghijk";
205        IccRecords iccRecords = Mockito.mock(IccRecords.class);
206        doReturn(subscriberId).when(iccRecords).getIMSI();
207        doReturn(iccRecords).when(mUiccController)
208                .getIccRecords(anyInt() /* phoneId */, eq(UiccController.APP_FAM_3GPP));
209
210        // Ensure the phone type is CdmaLte
211        GsmCdmaPhone spyPhone = spy(mPhoneUT);
212        doReturn(false).when(spyPhone).isPhoneTypeCdma();
213        doReturn(true).when(spyPhone).isPhoneTypeCdmaLte();
214        doReturn(false).when(spyPhone).isPhoneTypeGsm();
215
216        assertEquals(subscriberId, spyPhone.getSubscriberId());
217    }
218
219    @Test
220    @SmallTest
221    public void testGetSubscriberIdForCdmaPhone() {
222        final String subscriberId = "987654321";
223        doReturn(subscriberId).when(mSST).getImsi();
224
225        // Ensure the phone type is GSM
226        GsmCdmaPhone spyPhone = spy(mPhoneUT);
227        doReturn(true).when(spyPhone).isPhoneTypeCdma();
228        doReturn(false).when(spyPhone).isPhoneTypeCdmaLte();
229        doReturn(false).when(spyPhone).isPhoneTypeGsm();
230
231        assertEquals(subscriberId, spyPhone.getSubscriberId());
232    }
233
234    @Test
235    @SmallTest
236    public void testGetCellLocation() {
237        // GSM
238        CellLocation cellLocation = new GsmCellLocation();
239        WorkSource workSource = new WorkSource(Process.myUid(),
240            mContext.getPackageName());
241        doReturn(cellLocation).when(mSST).getCellLocation(workSource);
242        assertEquals(cellLocation, mPhoneUT.getCellLocation(workSource));
243
244        // Switch to CDMA
245        switchToCdma();
246
247        CdmaCellLocation cdmaCellLocation = new CdmaCellLocation();
248        cdmaCellLocation.setCellLocationData(0, 0, 0, 0, 0);
249        mSST.mCellLoc = cdmaCellLocation;
250
251        /*
252        LOCATION_MODE is a special case in SettingsProvider. Adding the special handling in mock
253        content provider is probably not worth the effort; it will also tightly couple tests with
254        SettingsProvider implementation.
255        // LOCATION_MODE_ON
256        Settings.Secure.putInt(mContext.getContentResolver(),
257                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
258        waitForMs(50);
259        CdmaCellLocation actualCellLocation = (CdmaCellLocation) mPhoneUT.getCellLocation();
260        assertEquals(0, actualCellLocation.getBaseStationLatitude());
261        assertEquals(0, actualCellLocation.getBaseStationLongitude());
262
263        // LOCATION_MODE_OFF
264        Settings.Secure.putInt(TestApplication.getAppContext().getContentResolver(),
265                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
266        waitForMs(50);
267        */
268
269        CdmaCellLocation actualCellLocation =
270                (CdmaCellLocation) mPhoneUT.getCellLocation(workSource);
271        assertEquals(CdmaCellLocation.INVALID_LAT_LONG,
272                actualCellLocation.getBaseStationLatitude());
273        assertEquals(CdmaCellLocation.INVALID_LAT_LONG,
274                actualCellLocation.getBaseStationLongitude());
275    }
276
277    @Test
278    @SmallTest
279    public void testGetPhoneType() {
280        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
281
282        // Switch to CDMA
283        switchToCdma();
284
285        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
286    }
287
288    @Test
289    @SmallTest
290    public void testGetDataConnectionState() {
291        // There are several cases possible. Testing few of them for now.
292        // 1. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn != APN_TYPE_EMERGENCY
293        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST).getCurrentDataConnectionState();
294        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
295                PhoneConstants.APN_TYPE_ALL));
296
297        // 2. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY, apn
298        // not connected
299        doReturn(DctConstants.State.IDLE).when(mDcTracker).getState(
300                PhoneConstants.APN_TYPE_EMERGENCY);
301        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
302                PhoneConstants.APN_TYPE_EMERGENCY));
303
304        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
305        // APN is connected, callTracker state = idle
306        doReturn(DctConstants.State.CONNECTED).when(mDcTracker).getState(
307                PhoneConstants.APN_TYPE_EMERGENCY);
308        mCT.mState = PhoneConstants.State.IDLE;
309        assertEquals(PhoneConstants.DataState.CONNECTED, mPhoneUT.getDataConnectionState(
310                PhoneConstants.APN_TYPE_EMERGENCY));
311
312        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
313        // APN enabled and CONNECTED, callTracker state != idle, !isConcurrentVoiceAndDataAllowed
314        mCT.mState = PhoneConstants.State.RINGING;
315        doReturn(false).when(mSST).isConcurrentVoiceAndDataAllowed();
316        assertEquals(PhoneConstants.DataState.SUSPENDED, mPhoneUT.getDataConnectionState(
317                PhoneConstants.APN_TYPE_EMERGENCY));
318    }
319
320    @Test
321    @SmallTest
322    public void testHandleInCallMmiCommands() {
323        try {
324            // Switch to CDMA
325            switchToCdma();
326
327            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
328
329            // Switch to GSM
330            switchToGsm();
331
332            mCT.mForegroundCall = mGsmCdmaCall;
333            mCT.mBackgroundCall = mGsmCdmaCall;
334            mCT.mRingingCall = mGsmCdmaCall;
335            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
336
337            // !isInCall
338            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
339
340            // isInCall
341            doReturn(GsmCdmaCall.State.ACTIVE).when(mGsmCdmaCall).getState();
342            assertTrue(mPhoneUT.handleInCallMmiCommands("0"));
343
344            // empty dialString
345            assertFalse(mPhoneUT.handleInCallMmiCommands(""));
346            assertFalse(mPhoneUT.handleInCallMmiCommands(null));
347
348        } catch (Exception e) {
349            fail(e.toString());
350        }
351    }
352
353    @Test
354    @SmallTest
355    public void testDial() {
356        try {
357            mSST.mSS = mServiceState;
358            doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
359
360            mCT.mForegroundCall = mGsmCdmaCall;
361            mCT.mBackgroundCall = mGsmCdmaCall;
362            mCT.mRingingCall = mGsmCdmaCall;
363            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
364
365            Connection connection = mPhoneUT.dial("1234567890",
366                    new PhoneInternalInterface.DialArgs.Builder().build());
367            verify(mCT).dial("1234567890", null, null);
368        } catch (CallStateException e) {
369            fail();
370        }
371    }
372
373    @Test
374    @SmallTest
375    public void testHandlePinMmi() {
376        assertFalse(mPhoneUT.handlePinMmi("1234567890"));
377    }
378
379    @Test
380    @SmallTest
381    public void testSendBurstDtmf() {
382        //Should do nothing for GSM
383        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
384        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
385                anyInt(), nullable(Message.class));
386
387        switchToCdma();
388        //invalid character
389        mPhoneUT.sendBurstDtmf("12345a67890", 0, 0, null);
390        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
391                anyInt(), nullable(Message.class));
392
393        //state IDLE
394        mCT.mState = PhoneConstants.State.IDLE;
395        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
396        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
397                anyInt(), nullable(Message.class));
398
399        //state RINGING
400        mCT.mState = PhoneConstants.State.RINGING;
401        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
402        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
403                anyInt(), nullable(Message.class));
404
405        mCT.mState = PhoneConstants.State.OFFHOOK;
406        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
407        verify(mSimulatedCommandsVerifier).sendBurstDtmf("1234567890", 0, 0, null);
408    }
409
410    @Test
411    @SmallTest
412    public void testVoiceMailNumberGsm() {
413        String voiceMailNumber = "1234567890";
414        // first test for GSM
415        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
416
417        // no resource or sharedPreference set -- should be null
418        assertEquals(null, mPhoneUT.getVoiceMailNumber());
419
420        // voicemail number from config
421        mContextFixture.getCarrierConfigBundle().
422                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
423        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
424
425        // voicemail number from config for roaming network
426        String voiceMailNumberForRoaming = "1234567892";
427        mContextFixture.getCarrierConfigBundle()
428                .putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING,
429                        voiceMailNumberForRoaming);
430        //Verify voicemail number for home
431        doReturn(false).when(mSST.mSS).getRoaming();
432        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
433        //Move to roaming condition, verify voicemail number for roaming
434        doReturn(true).when(mSST.mSS).getRoaming();
435        assertEquals(voiceMailNumberForRoaming, mPhoneUT.getVoiceMailNumber());
436        //Move to home condition, verify voicemail number for home
437        doReturn(false).when(mSST.mSS).getRoaming();
438        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
439
440        // voicemail number that is explicitly set
441        voiceMailNumber = "1234567891";
442        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
443        verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
444                nullable(Message.class));
445
446        doReturn(voiceMailNumber).when(mSimRecords).getVoiceMailNumber();
447        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
448    }
449
450    @Test
451    @SmallTest
452    public void testVoiceMailNumberCdma() {
453        switchToCdma();
454        String voiceMailNumber = "1234567890";
455
456        // no resource or sharedPreference set -- should be *86
457        assertEquals("*86", mPhoneUT.getVoiceMailNumber());
458
459        // config_telephony_use_own_number_for_voicemail
460        mContextFixture.getCarrierConfigBundle()
461                .putBoolean(CarrierConfigManager
462                                .KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, true);
463        doReturn(voiceMailNumber).when(mSST).getMdnNumber();
464        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
465
466        // voicemail number from config
467        voiceMailNumber = "1234567891";
468        mContextFixture.getCarrierConfigBundle().
469                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
470        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
471
472        // voicemail number from config for roaming network
473        String voiceMailNumberForRoaming = "1234567892";
474        mContextFixture.getCarrierConfigBundle()
475                .putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING,
476                        voiceMailNumberForRoaming);
477        //Verify voicemail number for home
478        doReturn(false).when(mSST.mSS).getRoaming();
479        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
480        //Move to roaming condition, verify voicemail number for roaming
481        doReturn(true).when(mSST.mSS).getRoaming();
482        assertEquals(voiceMailNumberForRoaming, mPhoneUT.getVoiceMailNumber());
483        //Move to home condition, verify voicemail number for home
484        doReturn(false).when(mSST.mSS).getRoaming();
485        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
486
487        // voicemail number from sharedPreference
488        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
489        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
490        verify(mRuimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
491                messageArgumentCaptor.capture());
492
493        Message msg = messageArgumentCaptor.getValue();
494        AsyncResult.forMessage(msg).exception =
495                new IccException("setVoiceMailNumber not implemented");
496        msg.sendToTarget();
497        waitForMs(50);
498
499        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
500    }
501
502    @FlakyTest
503    @Test
504    @Ignore
505    public void testVoiceMailCount() {
506        // initial value
507        assertEquals(0, mPhoneUT.getVoiceMessageCount());
508
509        // old sharedPreference set (testing upgrade from M to N scenario)
510        SharedPreferences sharedPreferences =
511                PreferenceManager.getDefaultSharedPreferences(mContext);
512        SharedPreferences.Editor editor = sharedPreferences.edit();
513        String imsi = "1234567890";
514        editor.putString("vm_id_key", imsi);
515        editor.putInt("vm_count_key", 5);
516        editor.apply();
517        doReturn(imsi).when(mSimRecords).getIMSI();
518
519        // updateVoiceMail should read old shared pref and delete it and new sharedPref should be
520        // updated now
521        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
522        mPhoneUT.updateVoiceMail();
523        assertEquals(5, mPhoneUT.getVoiceMessageCount());
524        assertEquals(null, sharedPreferences.getString("vm_id_key", null));
525        assertEquals(5, sharedPreferences.getInt("vm_count_key" + mPhoneUT.getSubId(), 0));
526
527        // sim records return count as 0, that overrides shared preference
528        doReturn(0).when(mSimRecords).getVoiceMessageCount();
529        mPhoneUT.updateVoiceMail();
530        assertEquals(0, mPhoneUT.getVoiceMessageCount());
531
532        // sim records return count as -1
533        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
534        mPhoneUT.updateVoiceMail();
535        assertEquals(-1, mPhoneUT.getVoiceMessageCount());
536
537        // sim records return count as -1 and sharedPreference says 0
538        mPhoneUT.setVoiceMessageCount(0);
539        mPhoneUT.updateVoiceMail();
540        assertEquals(-1, mPhoneUT.getVoiceMessageCount());
541
542        // sim records return count as -1 and sharedPreference says 2
543        mPhoneUT.setVoiceMessageCount(2);
544        mPhoneUT.updateVoiceMail();
545        assertEquals(2, mPhoneUT.getVoiceMessageCount());
546
547        // sim records return count as 0 and sharedPreference says 2
548        doReturn(0).when(mSimRecords).getVoiceMessageCount();
549        mPhoneUT.setVoiceMessageCount(2);
550        mPhoneUT.updateVoiceMail();
551        assertEquals(0, mPhoneUT.getVoiceMessageCount());
552    }
553
554    @Test
555    @SmallTest
556    public void testGetCallForwardingOption() {
557        // invalid reason (-1)
558        mPhoneUT.getCallForwardingOption(-1, null);
559        verify(mSimulatedCommandsVerifier, times(0)).queryCallForwardStatus(
560                anyInt(), anyInt(), nullable(String.class), nullable(Message.class));
561
562        // valid reason
563        String imsi = "1234567890";
564        doReturn(imsi).when(mSimRecords).getIMSI();
565        mPhoneUT.getCallForwardingOption(CF_REASON_UNCONDITIONAL, null);
566        verify(mSimulatedCommandsVerifier).queryCallForwardStatus(
567                eq(CF_REASON_UNCONDITIONAL), eq(CommandsInterface.SERVICE_CLASS_VOICE),
568                nullable(String.class), nullable(Message.class));
569        waitForMs(50);
570        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(),
571                nullable(String.class));
572
573        // should have updated shared preferences
574        SharedPreferences sharedPreferences = PreferenceManager.
575                getDefaultSharedPreferences(mContext);
576        assertEquals(IccRecords.CALL_FORWARDING_STATUS_DISABLED,
577                sharedPreferences.getInt(Phone.CF_STATUS + mPhoneUT.getSubId(),
578                        IccRecords.CALL_FORWARDING_STATUS_ENABLED));
579
580        // clean up
581        SharedPreferences.Editor editor = sharedPreferences.edit();
582        editor.remove(Phone.CF_STATUS + mPhoneUT.getSubId());
583        editor.apply();
584    }
585
586    @Test
587    @SmallTest
588    public void testSetCallForwardingOption() {
589        String cfNumber = "1234567890";
590
591        // invalid action
592        mPhoneUT.setCallForwardingOption(-1, CF_REASON_UNCONDITIONAL,
593                cfNumber, 0, null);
594        verify(mSimulatedCommandsVerifier, times(0)).setCallForward(anyInt(), anyInt(), anyInt(),
595                nullable(String.class), anyInt(), nullable(Message.class));
596
597        // valid action
598        mPhoneUT.setCallForwardingOption(CF_ACTION_ENABLE, CF_REASON_UNCONDITIONAL, cfNumber, 0,
599                null);
600        verify(mSimulatedCommandsVerifier).setCallForward(eq(CF_ACTION_ENABLE),
601                eq(CF_REASON_UNCONDITIONAL), anyInt(), eq(cfNumber), eq(0),
602                nullable(Message.class));
603        waitForMs(50);
604        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(), eq(cfNumber));
605    }
606
607    /**
608     * GsmCdmaPhone handles a lot of messages. This function verifies behavior for messages that are
609     * received when obj is created and that are received on phone type switch
610     */
611    @FlakyTest
612    @Ignore
613    @Test
614    @SmallTest
615    public void testHandleInitialMessages() {
616        // EVENT_RADIO_AVAILABLE
617        verify(mSimulatedCommandsVerifier).getBasebandVersion(nullable(Message.class));
618        verify(mSimulatedCommandsVerifier).getDeviceIdentity(nullable(Message.class));
619        verify(mSimulatedCommandsVerifier).getRadioCapability(nullable(Message.class));
620        // once as part of constructor, and once on radio available
621        verify(mSimulatedCommandsVerifier, times(2)).startLceService(anyInt(), anyBoolean(),
622                nullable(Message.class));
623
624        // EVENT_RADIO_ON
625        verify(mSimulatedCommandsVerifier).getVoiceRadioTechnology(nullable(Message.class));
626        verify(mSimulatedCommandsVerifier).setPreferredNetworkType(
627                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
628
629        // verify responses for above requests:
630        // baseband version
631        verify(mTelephonyManager).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
632                nullable(String.class));
633        // IMEI
634        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
635        // IMEISV
636        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
637        // radio capability
638        verify(mSimulatedCommandsVerifier).getNetworkSelectionMode(nullable(Message.class));
639
640        switchToCdma(); // this leads to eventRadioAvailable handling on cdma
641
642        // EVENT_RADIO_AVAILABLE
643        verify(mSimulatedCommandsVerifier, times(2)).getBasebandVersion(nullable(Message.class));
644        verify(mSimulatedCommandsVerifier, times(2)).getDeviceIdentity(nullable(Message.class));
645        verify(mSimulatedCommandsVerifier, times(3)).startLceService(anyInt(), anyBoolean(),
646                nullable(Message.class));
647
648        // EVENT_RADIO_ON
649        verify(mSimulatedCommandsVerifier, times(2)).getVoiceRadioTechnology(
650                nullable(Message.class));
651        // once on radio on, and once on get baseband version
652        verify(mSimulatedCommandsVerifier, times(3)).setPreferredNetworkType(
653                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
654
655        // verify responses for above requests:
656        // baseband version
657        verify(mTelephonyManager, times(2)).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
658                nullable(String.class));
659        // device identity
660        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
661        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
662        assertEquals(SimulatedCommands.FAKE_ESN, mPhoneUT.getEsn());
663        assertEquals(SimulatedCommands.FAKE_MEID, mPhoneUT.getMeid());
664    }
665
666    @Test
667    @SmallTest
668    public void testEmergencyCallbackMessages() {
669        verify(mSimulatedCommandsVerifier).setEmergencyCallbackMode(eq(mPhoneUT), anyInt(),
670                nullable(Object.class));
671        verify(mSimulatedCommandsVerifier).registerForExitEmergencyCallbackMode(eq(mPhoneUT),
672                anyInt(), nullable(Object.class));
673
674        // verify handling of emergency callback mode
675        mSimulatedCommands.notifyEmergencyCallbackMode();
676        waitForMs(50);
677
678        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
679        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
680        try {
681            verify(mIActivityManager, atLeast(1)).broadcastIntent(eq((IApplicationThread) null),
682                    intentArgumentCaptor.capture(),
683                    eq((String) null),
684                    eq((IIntentReceiver) null),
685                    eq(Activity.RESULT_OK),
686                    eq((String) null),
687                    eq((Bundle) null),
688                    eq((String[]) null),
689                    anyInt(),
690                    eq((Bundle) null),
691                    eq(false),
692                    eq(true),
693                    anyInt());
694        } catch(Exception e) {
695            fail("Unexpected exception: " + e.getStackTrace());
696        }
697
698        Intent intent = intentArgumentCaptor.getValue();
699        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
700        assertEquals(true, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, false));
701        assertEquals(true, mPhoneUT.isInEcm());
702
703        // verify that wakeLock is acquired in ECM
704        assertEquals(true, mPhoneUT.getWakeLock().isHeld());
705
706        mPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null);
707        mPhoneUT.registerForEmergencyCallToggle(mTestHandler, EVENT_EMERGENCY_CALL_TOGGLE, null);
708
709        // verify handling of emergency callback mode exit
710        mSimulatedCommands.notifyExitEmergencyCallbackMode();
711        waitForMs(50);
712
713        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
714        try {
715            verify(mIActivityManager, atLeast(2)).broadcastIntent(eq((IApplicationThread) null),
716                    intentArgumentCaptor.capture(),
717                    eq((String) null),
718                    eq((IIntentReceiver) null),
719                    eq(Activity.RESULT_OK),
720                    eq((String) null),
721                    eq((Bundle) null),
722                    eq((String[]) null),
723                    anyInt(),
724                    eq((Bundle) null),
725                    eq(false),
726                    eq(true),
727                    anyInt());
728        } catch(Exception e) {
729            fail("Unexpected exception: " + e.getStackTrace());
730        }
731
732        intent = intentArgumentCaptor.getValue();
733        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
734        assertEquals(false, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, true));
735        assertEquals(false, mPhoneUT.isInEcm());
736
737        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
738
739        // verify EcmExitRespRegistrant and mEmergencyCallToggledRegistrants are notified
740        verify(mTestHandler, times(2)).sendMessageAtTime(messageArgumentCaptor.capture(),
741                anyLong());
742        List<Message> msgList = messageArgumentCaptor.getAllValues();
743        assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, msgList.get(0).what);
744        assertEquals(EVENT_EMERGENCY_CALL_TOGGLE, msgList.get(1).what);
745
746        // verify setInternalDataEnabled
747        verify(mDcTracker).setInternalDataEnabled(true);
748
749        // verify wakeLock released
750        assertEquals(false, mPhoneUT.getWakeLock().isHeld());
751    }
752
753    @Test
754    @SmallTest
755    public void testModemResetInEmergencyCallbackMessages() {
756        verify(mSimulatedCommandsVerifier).setEmergencyCallbackMode(eq(mPhoneUT), anyInt(),
757                nullable(Object.class));
758        verify(mSimulatedCommandsVerifier).registerForModemReset(eq(mPhoneUT),
759                anyInt(), nullable(Object.class));
760
761        switchToCdma();
762        // verify handling of emergency callback mode
763        mSimulatedCommands.notifyEmergencyCallbackMode();
764        waitForMs(50);
765
766        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
767        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
768        try {
769            verify(mIActivityManager, atLeast(1)).broadcastIntent(eq((IApplicationThread) null),
770                    intentArgumentCaptor.capture(),
771                    eq((String) null),
772                    eq((IIntentReceiver) null),
773                    eq(Activity.RESULT_OK),
774                    eq((String) null),
775                    eq((Bundle) null),
776                    eq((String[]) null),
777                    anyInt(),
778                    eq((Bundle) null),
779                    eq(false),
780                    eq(true),
781                    anyInt());
782        } catch (Exception e) {
783            fail("Unexpected exception: " + e.getStackTrace());
784        }
785
786        Intent intent = intentArgumentCaptor.getValue();
787        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
788        assertEquals(true, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, false));
789        assertEquals(true, mPhoneUT.isInEcm());
790
791        // verify that wakeLock is acquired in ECM
792        assertEquals(true, mPhoneUT.getWakeLock().isHeld());
793
794        mPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null);
795        mPhoneUT.registerForEmergencyCallToggle(mTestHandler, EVENT_EMERGENCY_CALL_TOGGLE, null);
796
797        // verify handling of emergency callback mode exit when modem resets
798        mSimulatedCommands.notifyModemReset();
799        waitForMs(50);
800
801        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
802        try {
803            verify(mIActivityManager, atLeast(2)).broadcastIntent(eq((IApplicationThread) null),
804                    intentArgumentCaptor.capture(),
805                    eq((String) null),
806                    eq((IIntentReceiver) null),
807                    eq(Activity.RESULT_OK),
808                    eq((String) null),
809                    eq((Bundle) null),
810                    eq((String[]) null),
811                    anyInt(),
812                    eq((Bundle) null),
813                    eq(false),
814                    eq(true),
815                    anyInt());
816        } catch (Exception e) {
817            fail("Unexpected exception: " + e.getStackTrace());
818        }
819
820        intent = intentArgumentCaptor.getValue();
821        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
822        assertEquals(false, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, true));
823        assertEquals(false, mPhoneUT.isInEcm());
824
825        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
826
827        // verify EcmExitRespRegistrant and mEmergencyCallToggledRegistrants are notified
828        verify(mTestHandler, times(2)).sendMessageAtTime(messageArgumentCaptor.capture(),
829                anyLong());
830        List<Message> msgList = messageArgumentCaptor.getAllValues();
831        assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, msgList.get(0).what);
832        assertEquals(EVENT_EMERGENCY_CALL_TOGGLE, msgList.get(1).what);
833
834        // verify setInternalDataEnabled
835        verify(mDcTracker).setInternalDataEnabled(true);
836
837        // verify wakeLock released
838        assertEquals(false, mPhoneUT.getWakeLock().isHeld());
839    }
840
841    @Test
842    @SmallTest
843    public void testCallForwardingIndicator() {
844        doReturn(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN).when(mSimRecords).
845                getVoiceCallForwardingFlag();
846
847        // invalid subId
848        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubscriptionController).
849                getSubIdUsingPhoneId(anyInt());
850        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
851
852        // valid subId, sharedPreference not present
853        int subId1 = 0;
854        int subId2 = 1;
855        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
856        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
857
858        // old sharedPreference present
859        String imsi = "1234";
860        doReturn(imsi).when(mSimRecords).getIMSI();
861        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
862        SharedPreferences.Editor editor = sp.edit();
863        editor.putString(Phone.CF_ID, imsi);
864        editor.putInt(Phone.CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
865        editor.apply();
866        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
867
868        // old sharedPreference should be removed now
869        assertEquals(null, sp.getString(Phone.CF_ID, null));
870        assertEquals(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN,
871                sp.getInt(Phone.CF_ID, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN));
872
873        // now verify value from new sharedPreference
874        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
875
876        // check for another subId
877        doReturn(subId2).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
878        assertEquals(false, mPhoneUT.getCallForwardingIndicator());
879
880        // set value for the new subId in sharedPreference
881        editor.putInt(Phone.CF_STATUS + subId2, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
882        editor.apply();
883        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
884
885        // switching back to previous subId, stored value should still be available
886        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
887        assertEquals(true, mPhoneUT.getCallForwardingIndicator());
888
889        // cleanup
890        editor.remove(Phone.CF_STATUS + subId1);
891        editor.remove(Phone.CF_STATUS + subId2);
892        editor.apply();
893    }
894
895    @Test
896    @SmallTest
897    public void testEriLoading() {
898        mPhoneUT.mEriManager = mEriManager;
899        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_CARRIER_CONFIG_CHANGED,
900                null));
901        waitForMs(100);
902        verify(mEriManager, times(1)).loadEriFile();
903    }
904
905    @Test
906    @SmallTest
907    public void testGetIccCardUnknownAndAbsent() {
908        // If UiccSlot.isStateUnknown is true, we should return a dummy IccCard with the state
909        // set to UNKNOWN
910        doReturn(null).when(mUiccController).getUiccProfileForPhone(anyInt());
911        UiccSlot mockSlot = mock(UiccSlot.class);
912        doReturn(mockSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
913        doReturn(true).when(mockSlot).isStateUnknown();
914
915        IccCard iccCard = mPhoneUT.getIccCard();
916        assertEquals(IccCardConstants.State.UNKNOWN, iccCard.getState());
917
918        // if isStateUnknown is false, we should return a dummy IccCard with the state set to
919        // ABSENT
920        doReturn(false).when(mockSlot).isStateUnknown();
921        iccCard = mPhoneUT.getIccCard();
922        assertEquals(IccCardConstants.State.ABSENT, iccCard.getState());
923    }
924
925    @Test
926    @SmallTest
927    public void testGetEmptyIccCard() {
928        doReturn(null).when(mUiccController).getUiccProfileForPhone(anyInt());
929
930        IccCard iccCard = mPhoneUT.getIccCard();
931
932        // The iccCard should be a dummy object, not null.
933        assertTrue(!(iccCard instanceof UiccProfile));
934
935        assertTrue(iccCard != null);
936        assertEquals(IccCardConstants.State.UNKNOWN, iccCard.getState());
937        assertEquals(null, iccCard.getIccRecords());
938        assertEquals(false, iccCard.getIccLockEnabled());
939        assertEquals(false, iccCard.getIccFdnEnabled());
940        assertEquals(false, iccCard.isApplicationOnIcc(
941                IccCardApplicationStatus.AppType.APPTYPE_SIM));
942        assertEquals(false, iccCard.hasIccCard());
943        assertEquals(false, iccCard.getIccPin2Blocked());
944        assertEquals(false, iccCard.getIccPuk2Blocked());
945
946        Message onComplete = mTestHandler.obtainMessage(EVENT_SET_ICC_LOCK_ENABLED);
947        iccCard.setIccLockEnabled(true, "password", onComplete);
948
949        waitForMs(100);
950
951        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
952        // Verify that message is sent back with exception.
953        verify(mTestHandler, times(1)).sendMessageAtTime(messageArgumentCaptor.capture(),
954                anyLong());
955        Message message = messageArgumentCaptor.getAllValues().get(0);
956        AsyncResult ret = (AsyncResult) message.obj;
957        assertEquals(EVENT_SET_ICC_LOCK_ENABLED, message.what);
958        assertTrue(ret.exception != null);
959    }
960}
961