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 */
16package com.android.internal.telephony.uicc;
17import android.os.Handler;
18import android.os.HandlerThread;
19import android.os.Message;
20import android.test.suitebuilder.annotation.SmallTest;
21import org.junit.After;
22import org.junit.Before;
23import org.junit.Test;
24
25import com.android.internal.telephony.CommandsInterface;
26import com.android.internal.telephony.TelephonyTest;
27
28import org.mockito.ArgumentCaptor;
29import org.mockito.Mock;
30import static org.junit.Assert.assertEquals;
31import static org.junit.Assert.assertNotNull;
32import static org.junit.Assert.assertNull;
33import static org.mockito.Mockito.atLeast;
34import static org.mockito.Mockito.doReturn;
35import static org.mockito.Mockito.verify;
36import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
37
38public class UiccControllerTest extends TelephonyTest {
39    private UiccController mUiccControllerUT;
40    private UiccControllerHandlerThread mUiccControllerHandlerThread;
41    private static final int PHONE_COUNT = 1;
42    private static int ICC_CHANGED_EVENT = 0;
43    @Mock
44    private Handler mMockedHandler;
45    @Mock
46    private IccCardStatus mIccCardStatus;
47
48    private class UiccControllerHandlerThread extends HandlerThread {
49
50        private UiccControllerHandlerThread(String name) {
51            super(name);
52        }
53        @Override
54        public void onLooperPrepared() {
55            /* create a new UICC Controller associated with the simulated Commands */
56            mUiccControllerUT = UiccController.make(mContext,
57                    new CommandsInterface[]{mSimulatedCommands});
58            setReady(true);
59        }
60    }
61
62    private IccCardApplicationStatus composeUiccApplicationStatus(
63            IccCardApplicationStatus.AppType appType,
64            IccCardApplicationStatus.AppState appState, String aid) {
65        IccCardApplicationStatus mIccCardAppStatus = new IccCardApplicationStatus();
66        mIccCardAppStatus.aid = aid;
67        mIccCardAppStatus.app_type = appType;
68        mIccCardAppStatus.app_state = appState;
69        mIccCardAppStatus.pin1 = mIccCardAppStatus.pin2 =
70                IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
71        return mIccCardAppStatus;
72    }
73
74    @Before
75    public void setUp() throws Exception {
76        super.setUp(this.getClass().getSimpleName());
77
78        doReturn(PHONE_COUNT).when(mTelephonyManager).getPhoneCount();
79        doReturn(PHONE_COUNT).when(mTelephonyManager).getSimCount();
80
81        replaceInstance(UiccController.class, "mInstance", null, null);
82
83        /* null Application associated with any FAM */
84        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{};
85        mIccCardStatus.mCdmaSubscriptionAppIndex =
86                mIccCardStatus.mImsSubscriptionAppIndex =
87                        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
88        mSimulatedCommands.setIccCardStatus(mIccCardStatus);
89        mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG);
90        mUiccControllerHandlerThread.start();
91        waitUntilReady();
92        /* expected to get new UiccCards being created
93        wait till the async result and message delay */
94        waitForMs(100);
95    }
96
97    @After
98    public void tearDown() throws Exception {
99        mUiccControllerHandlerThread.quitSafely();
100        super.tearDown();
101    }
102
103    @Test @SmallTest
104    public void testSanity() {
105        assertEquals(PHONE_COUNT, mUiccControllerUT.getUiccCards().length);
106        assertNotNull(mUiccControllerUT.getUiccCard(0));
107        assertNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_3GPP));
108        assertNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_3GPP2));
109        assertNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_IMS));
110        assertNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_3GPP));
111        assertNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_3GPP2));
112        assertNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_IMS));
113    }
114
115    @Test @SmallTest
116    public void testPowerOff() {
117        /* Uicc Controller registered for event off to unavail */
118        logd("radio power state transition from off to unavail, dispose UICC Card");
119        testSanity();
120        mSimulatedCommands.requestShutdown(null);
121        waitForMs(50);
122        assertNull(mUiccControllerUT.getUiccCard(0));
123        assertEquals(CommandsInterface.RadioState.RADIO_UNAVAILABLE,
124                mSimulatedCommands.getRadioState());
125    }
126
127    @Test@SmallTest
128    public void testPowerOn() {
129        mSimulatedCommands.setRadioPower(true, null);
130        waitForMs(500);
131        assertNotNull(mUiccControllerUT.getUiccCard(0));
132        assertEquals(CommandsInterface.RadioState.RADIO_ON, mSimulatedCommands.getRadioState());
133    }
134
135    @Test @SmallTest
136    public void testPowerOffPowerOnWithApp() {
137         /* update app status and index */
138        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
139                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
140                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA0");
141        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
142                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
143                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA1");
144        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
145                IccCardApplicationStatus.AppType.APPTYPE_USIM,
146                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
147        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp};
148        mIccCardStatus.mCdmaSubscriptionAppIndex = 0;
149        mIccCardStatus.mImsSubscriptionAppIndex = 1;
150        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2;
151
152        mSimulatedCommands.setIccCardStatus(mIccCardStatus);
153        logd("radio power state transition from off to unavail");
154        testPowerOff();
155        /* UICC controller registered for event unavailable to on */
156        logd("radio power state transition from unavail to on, update IccCardStatus with app");
157        testPowerOn();
158
159        logd("validate Card status with Applications on it followed by Power on");
160        assertNotNull(mUiccControllerUT.getUiccCard(0));
161        assertNotNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_3GPP));
162        assertNotNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_3GPP2));
163        assertNotNull(mUiccControllerUT.getIccRecords(0, UiccController.APP_FAM_IMS));
164        assertNotNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_3GPP));
165        assertNotNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_3GPP2));
166        assertNotNull(mUiccControllerUT.getIccFileHandler(0, UiccController.APP_FAM_IMS));
167    }
168
169    @Test @SmallTest
170    public void testIccChangedListener() {
171        mUiccControllerUT.registerForIccChanged(mMockedHandler, ICC_CHANGED_EVENT, null);
172        testPowerOff();
173        ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class);
174        ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class);
175        verify(mMockedHandler, atLeast(1)).sendMessageDelayed(mCaptorMessage.capture(),
176                mCaptorLong.capture());
177        assertEquals(ICC_CHANGED_EVENT, mCaptorMessage.getValue().what);
178    }
179}
180