EuiccCardTest.java revision c8845bcb6daffaf186fb2b36edda545f28db2ed6
1/* 2 * Copyright (C) 2018 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.uicc.euicc; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.fail; 21import static org.mockito.ArgumentMatchers.any; 22import static org.mockito.ArgumentMatchers.eq; 23import static org.mockito.Mockito.times; 24import static org.mockito.Mockito.verify; 25 26import android.os.Handler; 27import android.os.HandlerThread; 28import android.service.euicc.EuiccProfileInfo; 29import android.util.ExceptionUtils; 30import android.util.Log; 31 32import com.android.internal.telephony.CommandsInterface; 33import com.android.internal.telephony.TelephonyTest; 34import com.android.internal.telephony.uicc.IccCardApplicationStatus; 35import com.android.internal.telephony.uicc.IccCardStatus; 36import com.android.internal.telephony.uicc.euicc.apdu.LogicalChannelMocker; 37import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback; 38 39import org.junit.After; 40import org.junit.Before; 41import org.junit.Test; 42import org.mockito.Mock; 43 44import java.util.concurrent.CountDownLatch; 45import java.util.concurrent.TimeUnit; 46 47public class EuiccCardTest extends TelephonyTest { 48 private static final long WAIT_TIMEOUT_MLLIS = 5000; 49 50 private static class ResultCaptor<T> extends AsyncResultCallback<T> { 51 public T result; 52 public Throwable exception; 53 54 private CountDownLatch mLatch; 55 56 private ResultCaptor() { 57 mLatch = new CountDownLatch(1); 58 } 59 60 public void await() { 61 try { 62 mLatch.await(WAIT_TIMEOUT_MLLIS, TimeUnit.MILLISECONDS); 63 } catch (InterruptedException e) { 64 fail("Execution is interrupted: " + e); 65 } 66 } 67 68 @Override 69 public void onResult(T r) { 70 result = r; 71 mLatch.countDown(); 72 } 73 74 @Override 75 public void onException(Throwable e) { 76 exception = e; 77 mLatch.countDown(); 78 } 79 } 80 81 private class UiccCardHandlerThread extends HandlerThread { 82 private UiccCardHandlerThread(String name) { 83 super(name); 84 } 85 86 @Override 87 public void onLooperPrepared() { 88 mEuiccCard = new EuiccCard(mContextFixture.getTestDouble(), mMockCi, mMockIccCardStatus, 89 0 /* phoneId */); 90 mHandler = new Handler(mTestHandlerThread.getLooper()); 91 setReady(true); 92 } 93 } 94 95 @Mock 96 private CommandsInterface mMockCi; 97 @Mock 98 private IccCardStatus mMockIccCardStatus; 99 100 private UiccCardHandlerThread mTestHandlerThread; 101 private Handler mHandler; 102 103 private EuiccCard mEuiccCard; 104 105 @Before 106 public void setUp() throws Exception { 107 super.setUp(getClass().getSimpleName()); 108 109 mMockIccCardStatus.mApplications = new IccCardApplicationStatus[]{}; 110 mMockIccCardStatus.mCdmaSubscriptionAppIndex = 111 mMockIccCardStatus.mImsSubscriptionAppIndex = 112 mMockIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1; 113 mMockIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT; 114 115 mTestHandlerThread = new UiccCardHandlerThread(getClass().getSimpleName()); 116 mTestHandlerThread.start(); 117 118 waitUntilReady(); 119 } 120 121 @After 122 public void tearDown() throws Exception { 123 mTestHandlerThread.quit(); 124 super.tearDown(); 125 } 126 127 private void assertUnexpectedException(Throwable e) { 128 if (e != null) { 129 fail("Unexpected exception: " + ExceptionUtils.getCompleteMessage(e) + "\n-----\n" 130 + Log.getStackTraceString(e.getCause()) + "-----"); 131 } 132 } 133 134 @Test 135 public void testGetAllProfiles() { 136 int channel = mockLogicalChannelResponses( 137 "BF2D14A012E3105A0A896700000000004523019F7001019000"); 138 139 ResultCaptor<EuiccProfileInfo[]> resultCaptor = new ResultCaptor<>(); 140 mEuiccCard.getAllProfiles(resultCaptor, mHandler); 141 resultCaptor.await(); 142 143 assertUnexpectedException(resultCaptor.exception); 144 EuiccProfileInfo[] profiles = resultCaptor.result; 145 assertEquals(1, profiles.length); 146 assertEquals("98760000000000543210", profiles[0].getIccid()); 147 assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profiles[0].getState()); 148 verifyStoreData(channel, "BF2D0D5C0B5A909192B79F709599BF76"); 149 } 150 151 @Test 152 public void testFSuffix() { 153 // iccID is 987600000000005432FF. 154 int channel = mockLogicalChannelResponses( 155 "BF2D14A012E3105A0A896700000000004523FF9F7001019000"); 156 157 ResultCaptor<EuiccProfileInfo[]> resultCaptor = new ResultCaptor<>(); 158 mEuiccCard.getAllProfiles(resultCaptor, mHandler); 159 resultCaptor.await(); 160 161 assertUnexpectedException(resultCaptor.exception); 162 EuiccProfileInfo[] profiles = resultCaptor.result; 163 assertEquals(1, profiles.length); 164 assertEquals("987600000000005432", profiles[0].getIccid()); 165 assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profiles[0].getState()); 166 verifyStoreData(channel, "BF2D0D5C0B5A909192B79F709599BF76"); 167 } 168 169 @Test 170 public void testDisableProfile() { 171 int channel = mockLogicalChannelResponses("BF32038001009000"); 172 173 ResultCaptor<Void> resultCaptor = new ResultCaptor<>(); 174 mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler); 175 resultCaptor.await(); 176 177 assertUnexpectedException(resultCaptor.exception); 178 verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF"); 179 } 180 181 @Test 182 public void testDisableProfile_SimRefresh() { 183 int channel = mockLogicalChannelResponses("6106", "6f00"); 184 185 ResultCaptor<Void> resultCaptor = new ResultCaptor<>(); 186 mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler); 187 resultCaptor.await(); 188 189 assertUnexpectedException(resultCaptor.exception); 190 verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF"); 191 } 192 193 @Test 194 public void testDisableProfile_Error() { 195 int channel = mockLogicalChannelResponses("BF32038001039000"); 196 197 ResultCaptor<Void> resultCaptor = new ResultCaptor<>(); 198 mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler); 199 resultCaptor.await(); 200 201 assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode()); 202 verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF"); 203 } 204 205 private void verifyStoreData(int channel, String command) { 206 verify(mMockCi, times(1)) 207 .iccTransmitApduLogicalChannel(eq(channel), eq(0x80 | channel), eq(0xE2), eq(0x91), 208 eq(0), eq(command.length() / 2), eq(command), any()); 209 } 210 211 private int mockLogicalChannelResponses(Object... responses) { 212 int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, 213 "E00582030200009000"); 214 LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, responses); 215 LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel); 216 return channel; 217 } 218} 219