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; 17 18import android.os.Handler; 19import android.os.HandlerThread; 20import android.os.Message; 21import android.test.suitebuilder.annotation.SmallTest; 22 23import org.junit.After; 24import org.junit.Before; 25import org.junit.Test; 26 27import com.android.internal.telephony.TelephonyTest; 28import com.android.internal.telephony.cat.CatService; 29import org.mockito.ArgumentCaptor; 30import org.mockito.Mock; 31import static org.mockito.Mockito.*; 32 33import static org.junit.Assert.assertEquals; 34import static org.junit.Assert.assertFalse; 35import static org.junit.Assert.assertNull; 36import static org.junit.Assert.assertTrue; 37import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 38 39public class UiccCardTest extends TelephonyTest { 40 private UiccCard mUicccard; 41 42 public UiccCardTest() { 43 super(); 44 } 45 46 private IccIoResult mIccIoResult; 47 48 private UiccCardHandlerThread mTestHandlerThread; 49 private Handler mHandler; 50 private static final int UICCCARD_UPDATE_CARD_STATE_EVENT = 1; 51 private static final int UICCCARD_UPDATE_CARD_APPLICATION_EVENT = 2; 52 private static final int UICCCARD_CARRIER_PRIVILEDGE_LOADED_EVENT = 3; 53 private static final int UICCCARD_ABSENT = 4; 54 55 @Mock 56 private CatService mCAT; 57 @Mock 58 private IccCardStatus mIccCardStatus; 59 @Mock 60 private Handler mMockedHandler; 61 62 63 private class UiccCardHandlerThread extends HandlerThread { 64 65 private UiccCardHandlerThread(String name) { 66 super(name); 67 } 68 69 @Override 70 public void onLooperPrepared() { 71 mUicccard = new UiccCard(mContextFixture.getTestDouble(), 72 mSimulatedCommands, mIccCardStatus); 73 /* create a custom handler for the Handler Thread */ 74 mHandler = new Handler(mTestHandlerThread.getLooper()) { 75 @Override 76 public void handleMessage(Message msg) { 77 switch (msg.what) { 78 case UICCCARD_UPDATE_CARD_STATE_EVENT: 79 /* Upon handling this event, new CarrierPrivilegeRule 80 will be created with the looper of HandlerThread */ 81 logd("Update UICC Card State"); 82 mUicccard.update(mContextFixture.getTestDouble(), 83 mSimulatedCommands, mIccCardStatus); 84 setReady(true); 85 break; 86 case UICCCARD_UPDATE_CARD_APPLICATION_EVENT: 87 logd("Update UICC Card Applications"); 88 mUicccard.update(mContextFixture.getTestDouble(), 89 mSimulatedCommands, mIccCardStatus); 90 setReady(true); 91 break; 92 default: 93 logd("Unknown Event " + msg.what); 94 } 95 } 96 }; 97 98 setReady(true); 99 logd("create UiccCard"); 100 } 101 } 102 103 private IccCardApplicationStatus composeUiccApplicationStatus( 104 IccCardApplicationStatus.AppType appType, 105 IccCardApplicationStatus.AppState appState, String aid) { 106 IccCardApplicationStatus mIccCardAppStatus = new IccCardApplicationStatus(); 107 mIccCardAppStatus.aid = aid; 108 mIccCardAppStatus.app_type = appType; 109 mIccCardAppStatus.app_state = appState; 110 mIccCardAppStatus.pin1 = mIccCardAppStatus.pin2 = 111 IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED; 112 return mIccCardAppStatus; 113 } 114 115 @Before 116 public void setUp() throws Exception { 117 118 super.setUp(getClass().getSimpleName()); 119 /* initially there are no application available */ 120 mIccCardStatus.mApplications = new IccCardApplicationStatus[]{}; 121 mIccCardStatus.mCdmaSubscriptionAppIndex = 122 mIccCardStatus.mImsSubscriptionAppIndex = 123 mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1; 124 125 mIccIoResult = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes("FF40")); 126 mSimulatedCommands.setIccIoResultForApduLogicalChannel(mIccIoResult); 127 /* starting the Handler Thread */ 128 mTestHandlerThread = new UiccCardHandlerThread(TAG); 129 mTestHandlerThread.start(); 130 131 waitUntilReady(); 132 replaceInstance(UiccCard.class, "mCatService", mUicccard, mCAT); 133 } 134 135 @After 136 public void tearDown() throws Exception { 137 mTestHandlerThread.quit(); 138 super.tearDown(); 139 } 140 141 @Test 142 @SmallTest 143 public void tesUiccCartdInfoSanity() { 144 /* before update sanity test */ 145 assertEquals(0, mUicccard.getNumApplications()); 146 assertNull(mUicccard.getCardState()); 147 assertNull(mUicccard.getUniversalPinState()); 148 assertNull(mUicccard.getOperatorBrandOverride()); 149 /* CarrierPrivilegeRule equals null, return true */ 150 assertTrue(mUicccard.areCarrierPriviligeRulesLoaded()); 151 for (IccCardApplicationStatus.AppType mAppType : 152 IccCardApplicationStatus.AppType.values()) { 153 assertFalse(mUicccard.isApplicationOnIcc(mAppType)); 154 } 155 } 156 157 @Test @SmallTest 158 public void testUpdateUiccCardApplication() { 159 /* update app status and index */ 160 IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus( 161 IccCardApplicationStatus.AppType.APPTYPE_CSIM, 162 IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA0"); 163 IccCardApplicationStatus imsApp = composeUiccApplicationStatus( 164 IccCardApplicationStatus.AppType.APPTYPE_ISIM, 165 IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA1"); 166 IccCardApplicationStatus umtsApp = composeUiccApplicationStatus( 167 IccCardApplicationStatus.AppType.APPTYPE_USIM, 168 IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2"); 169 mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp}; 170 mIccCardStatus.mCdmaSubscriptionAppIndex = 0; 171 mIccCardStatus.mImsSubscriptionAppIndex = 1; 172 mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2; 173 Message mCardUpdate = mHandler.obtainMessage(UICCCARD_UPDATE_CARD_APPLICATION_EVENT); 174 setReady(false); 175 mCardUpdate.sendToTarget(); 176 177 waitUntilReady(); 178 179 assertEquals(3, mUicccard.getNumApplications()); 180 assertTrue(mUicccard.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_CSIM)); 181 assertTrue(mUicccard.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_ISIM)); 182 assertTrue(mUicccard.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_USIM)); 183 } 184 185 @Test @SmallTest 186 public void testUpdateUiccCardState() { 187 int mChannelId = 1; 188 /* set card as present */ 189 mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT; 190 /* Mock open Channel ID 1 */ 191 mSimulatedCommands.setOpenChannelId(mChannelId); 192 Message mCardUpdate = mHandler.obtainMessage(UICCCARD_UPDATE_CARD_STATE_EVENT); 193 setReady(false); 194 mCardUpdate.sendToTarget(); 195 /* try to create a new CarrierPrivilege, loading state -> loaded state */ 196 /* wait till the async result and message delay */ 197 waitUntilReady(); 198 199 assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUicccard.getCardState()); 200 201 waitForMs(50); 202 203 assertTrue(mUicccard.areCarrierPriviligeRulesLoaded()); 204 verify(mSimulatedCommandsVerifier, times(1)).iccOpenLogicalChannel(isA(String.class), 205 anyInt(), isA(Message.class)); 206 verify(mSimulatedCommandsVerifier, times(1)).iccTransmitApduLogicalChannel( 207 eq(mChannelId), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyString(), 208 isA(Message.class) 209 ); 210 } 211 212 @Test @SmallTest 213 public void testUpdateUiccCardPinState() { 214 mIccCardStatus.mUniversalPinState = IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED; 215 mUicccard.update(mContextFixture.getTestDouble(), mSimulatedCommands, mIccCardStatus); 216 assertEquals(IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED, 217 mUicccard.getUniversalPinState()); 218 } 219 220 @Test @SmallTest 221 public void testCarrierPriviledgeLoadedListener() { 222 mUicccard.registerForCarrierPrivilegeRulesLoaded(mMockedHandler, 223 UICCCARD_CARRIER_PRIVILEDGE_LOADED_EVENT, null); 224 ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class); 225 ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class); 226 testUpdateUiccCardState(); 227 verify(mMockedHandler, atLeast(1)).sendMessageDelayed(mCaptorMessage.capture(), 228 mCaptorLong.capture()); 229 assertEquals(UICCCARD_CARRIER_PRIVILEDGE_LOADED_EVENT, mCaptorMessage.getValue().what); 230 } 231 232 @Test @SmallTest 233 public void testCardAbsentListener() { 234 mUicccard.registerForAbsent(mMockedHandler, UICCCARD_ABSENT, null); 235 /* assume hotswap capable, avoid bootup on card removal */ 236 mContextFixture.putBooleanResource(com.android.internal.R.bool.config_hotswapCapable, true); 237 mSimulatedCommands.setRadioPower(true, null); 238 239 /* Mock Card State transition from card_present to card_absent */ 240 logd("UICC Card Present update"); 241 mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT; 242 Message mCardUpdate = mHandler.obtainMessage(UICCCARD_UPDATE_CARD_STATE_EVENT); 243 mCardUpdate.sendToTarget(); 244 waitForMs(50); 245 246 logd("UICC Card absent update"); 247 mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_ABSENT; 248 mUicccard.update(mContextFixture.getTestDouble(), mSimulatedCommands, mIccCardStatus); 249 waitForMs(50); 250 251 ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class); 252 ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class); 253 verify(mMockedHandler, atLeast(1)).sendMessageDelayed(mCaptorMessage.capture(), 254 mCaptorLong.capture()); 255 assertEquals(UICCCARD_ABSENT, mCaptorMessage.getValue().what); 256 } 257} 258