EuiccCardTest.java revision 4d59805cd9a6ad9e0f5a5dc87c1fd2a619150b36
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.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertTrue;
23import static org.junit.Assert.fail;
24import static org.mockito.ArgumentMatchers.any;
25import static org.mockito.ArgumentMatchers.eq;
26import static org.mockito.Mockito.times;
27import static org.mockito.Mockito.verify;
28
29import android.os.Handler;
30import android.os.HandlerThread;
31import android.service.carrier.CarrierIdentifier;
32import android.service.euicc.EuiccProfileInfo;
33import android.telephony.UiccAccessRule;
34import android.telephony.euicc.EuiccCardManager;
35import android.telephony.euicc.EuiccNotification;
36import android.telephony.euicc.EuiccRulesAuthTable;
37import android.util.ExceptionUtils;
38import android.util.Log;
39
40import com.android.internal.telephony.CommandsInterface;
41import com.android.internal.telephony.TelephonyTest;
42import com.android.internal.telephony.uicc.IccCardApplicationStatus;
43import com.android.internal.telephony.uicc.IccCardStatus;
44import com.android.internal.telephony.uicc.IccUtils;
45import com.android.internal.telephony.uicc.asn1.Asn1Node;
46import com.android.internal.telephony.uicc.euicc.apdu.LogicalChannelMocker;
47import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
48
49import org.junit.After;
50import org.junit.Before;
51import org.junit.Test;
52import org.mockito.Mock;
53
54import java.util.concurrent.CountDownLatch;
55import java.util.concurrent.TimeUnit;
56
57public class EuiccCardTest extends TelephonyTest {
58    private static final long WAIT_TIMEOUT_MLLIS = 5000;
59
60    private static class ResultCaptor<T> extends AsyncResultCallback<T> {
61        public T result;
62        public Throwable exception;
63
64        private CountDownLatch mLatch;
65
66        private ResultCaptor() {
67            mLatch = new CountDownLatch(1);
68        }
69
70        public void await() {
71            try {
72                mLatch.await(WAIT_TIMEOUT_MLLIS, TimeUnit.MILLISECONDS);
73            } catch (InterruptedException e) {
74                fail("Execution is interrupted: " + e);
75            }
76        }
77
78        @Override
79        public void onResult(T r) {
80            result = r;
81            mLatch.countDown();
82        }
83
84        @Override
85        public void onException(Throwable e) {
86            exception = e;
87            mLatch.countDown();
88        }
89    }
90
91    private class UiccCardHandlerThread extends HandlerThread {
92        private UiccCardHandlerThread(String name) {
93            super(name);
94        }
95
96        @Override
97        public void onLooperPrepared() {
98            mEuiccCard =
99                    new EuiccCard(mContextFixture.getTestDouble(), mMockCi, mMockIccCardStatus,
100                            0 /* phoneId */) {
101                        @Override
102                        protected byte[] getDeviceId() {
103                            return IccUtils.bcdToBytes("987654321012345");
104                        }
105                    };
106            mHandler = new Handler(mTestHandlerThread.getLooper());
107            setReady(true);
108        }
109    }
110
111    @Mock
112    private CommandsInterface mMockCi;
113    @Mock
114    private IccCardStatus mMockIccCardStatus;
115
116    private UiccCardHandlerThread mTestHandlerThread;
117    private Handler mHandler;
118
119    private EuiccCard mEuiccCard;
120
121    @Before
122    public void setUp() throws Exception {
123        super.setUp(getClass().getSimpleName());
124
125        mMockIccCardStatus.mApplications = new IccCardApplicationStatus[]{};
126        mMockIccCardStatus.mCdmaSubscriptionAppIndex =
127                mMockIccCardStatus.mImsSubscriptionAppIndex =
128                        mMockIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
129        mMockIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT;
130
131        mTestHandlerThread = new UiccCardHandlerThread(getClass().getSimpleName());
132        mTestHandlerThread.start();
133
134        waitUntilReady();
135    }
136
137    @After
138    public void tearDown() throws Exception {
139        mTestHandlerThread.quit();
140        super.tearDown();
141    }
142
143    private void assertUnexpectedException(Throwable e) {
144        if (e != null) {
145            fail("Unexpected exception: " + ExceptionUtils.getCompleteMessage(e) + "\n-----\n"
146                    + Log.getStackTraceString(e.getCause()) + "-----");
147        }
148    }
149
150    @Test
151    public void testGetAllProfiles() {
152        int channel = mockLogicalChannelResponses(
153                "BF2D14A012E3105A0A896700000000004523019F7001019000");
154
155        ResultCaptor<EuiccProfileInfo[]> resultCaptor = new ResultCaptor<>();
156        mEuiccCard.getAllProfiles(resultCaptor, mHandler);
157        resultCaptor.await();
158
159        assertUnexpectedException(resultCaptor.exception);
160        EuiccProfileInfo[] profiles = resultCaptor.result;
161        assertEquals(1, profiles.length);
162        assertEquals("98760000000000543210", profiles[0].getIccid());
163        assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profiles[0].getState());
164        verifyStoreData(channel, "BF2D0D5C0B5A909192B79F709599BF76");
165    }
166
167    @Test
168    public void testFSuffix() {
169        // iccID is 987600000000005432FF.
170        int channel = mockLogicalChannelResponses(
171                "BF2D14A012E3105A0A896700000000004523FF9F7001019000");
172
173        ResultCaptor<EuiccProfileInfo[]> resultCaptor = new ResultCaptor<>();
174        mEuiccCard.getAllProfiles(resultCaptor, mHandler);
175        resultCaptor.await();
176
177        EuiccProfileInfo[] profiles = resultCaptor.result;
178        assertEquals(1, profiles.length);
179        assertEquals("987600000000005432", profiles[0].getIccid());
180        assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profiles[0].getState());
181        verifyStoreData(channel, "BF2D0D5C0B5A909192B79F709599BF76");
182    }
183
184    @Test
185    public void testGetProfile() {
186        int channel = mockLogicalChannelResponses("BF2D8184A08181E37F"
187                + "5A0A89670000000000452301" // ICCID
188                + "90046E69636B" // Nickname
189                + "9103746D6F" // Service provider name
190                + "92027031" // Profile name
191                + "B70F800312F34581030102038203040506" // Operator id
192                + "9F700101" // Profile state
193                + "950101" // Profile class
194                + "990206C0" // Policy rules
195                + "BF7645E243E135C114ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4"
196                + "CA1D636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070"
197                + "E30ADB080000000000000001" // Carrier privilege rules
198                + "9000");
199
200        ResultCaptor<EuiccProfileInfo> resultCaptor = new ResultCaptor<>();
201        mEuiccCard.getProfile("98760000000000543210", resultCaptor, mHandler);
202        resultCaptor.await();
203
204        EuiccProfileInfo profile = resultCaptor.result;
205        assertEquals("98760000000000543210", profile.getIccid());
206        assertEquals("nick", profile.getNickname());
207        assertEquals("tmo", profile.getServiceProviderName());
208        assertEquals("p1", profile.getProfileName());
209        assertEquals("213", profile.getCarrierIdentifier().getMcc());
210        assertEquals("54", profile.getCarrierIdentifier().getMnc());
211        assertEquals("010203", profile.getCarrierIdentifier().getGid1());
212        assertEquals("040506", profile.getCarrierIdentifier().getGid2());
213        assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profile.getState());
214        assertEquals(EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, profile.getProfileClass());
215        assertEquals(
216                EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE
217                        | EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE,
218                profile.getPolicyRules());
219        assertArrayEquals(
220                new UiccAccessRule[] {
221                        new UiccAccessRule(
222                                IccUtils.hexStringToBytes(
223                                        "ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4"),
224                                "com.google.android.apps.myapp", 1)
225                },
226                profile.getUiccAccessRules().toArray());
227        verifyStoreData(channel, "BF2D195A0A896700000000004523015C0B5A909192B79F709599BF76");
228    }
229
230    @Test
231    public void testDisableProfile() {
232        int channel = mockLogicalChannelResponses("BF32038001009000");
233
234        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
235        mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler);
236        resultCaptor.await();
237
238        assertUnexpectedException(resultCaptor.exception);
239        verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF");
240    }
241
242    @Test
243    public void testDisableProfile_SimRefresh() {
244        int channel = mockLogicalChannelResponses("6106", "6f00");
245
246        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
247        mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler);
248        resultCaptor.await();
249
250        assertUnexpectedException(resultCaptor.exception);
251        verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF");
252    }
253
254    @Test
255    public void testDisableProfile_Error() {
256        int channel = mockLogicalChannelResponses("BF32038001039000");
257
258        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
259        mEuiccCard.disableProfile("98760000000000543210", true, resultCaptor, mHandler);
260        resultCaptor.await();
261
262        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
263        verifyStoreData(channel, "BF3211A00C5A0A896700000000004523018101FF");
264    }
265
266    @Test
267    public void testSwitchToProfile() {
268        int channel = mockLogicalChannelResponses("BF31038001009000");
269
270        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
271        mEuiccCard.switchToProfile("98760000000000543210", true, resultCaptor, mHandler);
272        resultCaptor.await();
273
274        assertUnexpectedException(resultCaptor.exception);
275        verifyStoreData(channel, "BF3111A00C5A0A896700000000004523018101FF");
276    }
277
278    @Test
279    public void testSwitchToProfile_SimRefresh() {
280        int channel = mockLogicalChannelResponses("6106", "6f00");
281
282        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
283        mEuiccCard.switchToProfile("98760000000000543210", true, resultCaptor, mHandler);
284        resultCaptor.await();
285
286        assertUnexpectedException(resultCaptor.exception);
287        verifyStoreData(channel, "BF3111A00C5A0A896700000000004523018101FF");
288    }
289
290    @Test
291    public void testSwitchToProfile_Error() {
292        int channel = mockLogicalChannelResponses("BF31038001039000");
293
294        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
295        mEuiccCard.switchToProfile("98760000000000543210", true, resultCaptor, mHandler);
296        resultCaptor.await();
297
298        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
299        verifyStoreData(channel, "BF3111A00C5A0A896700000000004523018101FF");
300    }
301
302    @Test
303    public void testGetEid() {
304        int channel = mockLogicalChannelResponses("BF3E065A041A2B3C4D9000");
305
306        ResultCaptor<String> resultCaptor = new ResultCaptor<>();
307        mEuiccCard.getEid(resultCaptor, mHandler);
308        resultCaptor.await();
309
310        assertEquals("1A2B3C4D", resultCaptor.result);
311        verifyStoreData(channel, "BF3E035C015A");
312    }
313
314    @Test
315    public void testSetNickname() {
316        int channel = mockLogicalChannelResponses("BF29038001009000");
317
318        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
319        mEuiccCard.setNickname("98760000000000543210", "new nickname", resultCaptor, mHandler);
320        resultCaptor.await();
321
322        assertUnexpectedException(resultCaptor.exception);
323        verifyStoreData(channel, "BF291A5A0A89670000000000452301900C6E6577206E69636B6E616D65");
324    }
325
326    @Test
327    public void testDeleteProfile() {
328        int channel = mockLogicalChannelResponses("BF33038001009000");
329
330        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
331        mEuiccCard.deleteProfile("98760000000000543210", resultCaptor, mHandler);
332        resultCaptor.await();
333
334        assertUnexpectedException(resultCaptor.exception);
335        verifyStoreData(channel, "BF330C5A0A89670000000000452301");
336    }
337
338    @Test
339    public void testDeleteProfile_Error() {
340        int channel = mockLogicalChannelResponses("BF33038001039000");
341
342        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
343        mEuiccCard.deleteProfile("98760000000000543210", resultCaptor, mHandler);
344        resultCaptor.await();
345
346        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
347        verifyStoreData(channel, "BF330C5A0A89670000000000452301");
348    }
349
350    @Test
351    public void testGetDefaultSmdpAddress() {
352        int channel = mockLogicalChannelResponses(
353                "BF3C148008534D44502E434F4D8108736D64732E636F6D9000");
354
355        ResultCaptor<String> resultCaptor = new ResultCaptor<>();
356        mEuiccCard.getDefaultSmdpAddress(resultCaptor, mHandler);
357        resultCaptor.await();
358
359        assertEquals("SMDP.COM", resultCaptor.result);
360        verifyStoreData(channel, "BF3C00");
361    }
362
363    @Test
364    public void testGetSmdsAddress() {
365        int channel = mockLogicalChannelResponses(
366                "BF3C148008534D44502E434F4D8108736D64732E636F6D9000");
367
368        ResultCaptor<String> resultCaptor = new ResultCaptor<>();
369        mEuiccCard.getSmdsAddress(resultCaptor, mHandler);
370        resultCaptor.await();
371
372        assertEquals("smds.com", resultCaptor.result);
373        verifyStoreData(channel, "BF3C00");
374    }
375
376    @Test
377    public void testSetDefaultSmdpAddress() {
378        int channel = mockLogicalChannelResponses("BF3F038001009000");
379
380        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
381        mEuiccCard.setDefaultSmdpAddress("smdp.gsma.com", resultCaptor, mHandler);
382        resultCaptor.await();
383
384        assertUnexpectedException(resultCaptor.exception);
385        verifyStoreData(channel, "BF3F0F800D736D64702E67736D612E636F6D");
386    }
387
388    @Test
389    public void testGetRulesAuthTable() {
390        int channel = mockLogicalChannelResponses("BF4347"
391                + "A021" // Rule #1
392                + "800206C0" // Policy rules: DO_NOT_DELETE | DO_NOT_DISABLE
393                + "A118" // Operator IDs
394                + "B70A800312F3458103010203" // ID #1: 213, 54, [1,2,3], null
395                + "B70A800312F3458203040506" // ID #2: 213, 54, null, [4,5,6]
396                + "820108" // Flag (no user consent)
397                + "A022" // Rule #2
398                + "80020780" // Policy rules: DO_NOT_DISABLE
399                + "A118" // Operator IDs
400                + "B70A800312E3458103010203" // ID #1: 213, 54E, [1,2,3], null
401                + "B70A8003EEEE458203040506" // ID #2: EEE, 54E, null, [4,5,6]
402                + "82020780" // Flag (user consent)
403                + "9000");
404
405        ResultCaptor<EuiccRulesAuthTable> resultCaptor = new ResultCaptor<>();
406        mEuiccCard.getRulesAuthTable(resultCaptor, mHandler);
407        resultCaptor.await();
408
409        EuiccRulesAuthTable rat = resultCaptor.result;
410        assertEquals(-1,
411                rat.findIndex(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE,
412                        new CarrierIdentifier(new byte[] {0x12, (byte) 0xF3, 0x45}, null, null)));
413        assertEquals(1,
414                rat.findIndex(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE,
415                        new CarrierIdentifier(new byte[] {0x23, 0x67, 0x45}, null, "040506")));
416        assertFalse(rat.hasPolicyRuleFlag(0,
417                EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED));
418        assertTrue(rat.hasPolicyRuleFlag(1,
419                EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED));
420        verifyStoreData(channel, "BF4300");
421    }
422
423    @Test
424    public void testResetMemory() {
425        int channel = mockLogicalChannelResponses("BF34038001009000");
426
427        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
428        mEuiccCard.resetMemory(EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
429                resultCaptor, mHandler);
430        resultCaptor.await();
431
432        assertUnexpectedException(resultCaptor.exception);
433        verifyStoreData(channel, "BF340482020640");
434    }
435
436    @Test
437    public void testResetMemory_SimRefresh() {
438        int channel = mockLogicalChannelResponses("6106", "6f00");
439
440        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
441        mEuiccCard.resetMemory(EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
442                resultCaptor, mHandler);
443        resultCaptor.await();
444
445        assertUnexpectedException(resultCaptor.exception);
446        verifyStoreData(channel, "BF340482020640");
447    }
448
449    @Test
450    public void testGetEuiccChallenge() {
451        int channel = mockLogicalChannelResponses("BF2E0580030102039000");
452
453        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
454        mEuiccCard.getEuiccChallenge(resultCaptor, mHandler);
455        resultCaptor.await();
456
457        assertArrayEquals(new byte[] {1, 2, 3}, resultCaptor.result);
458        verifyStoreData(channel, "BF2E00");
459    }
460
461    @Test
462    public void testGetEuiccInfo1() {
463        int channel = mockLogicalChannelResponses("BF20030102039000");
464
465        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
466        mEuiccCard.getEuiccInfo1(resultCaptor, mHandler);
467        resultCaptor.await();
468
469        assertEquals("BF2003010203", IccUtils.bytesToHexString(resultCaptor.result));
470        verifyStoreData(channel, "BF2000");
471    }
472
473    @Test
474    public void testGetEuiccInfo2() {
475        int channel = mockLogicalChannelResponses("BF22030102039000");
476
477        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
478        mEuiccCard.getEuiccInfo2(resultCaptor, mHandler);
479        resultCaptor.await();
480
481        assertEquals("BF2203010203", IccUtils.bytesToHexString(resultCaptor.result));
482        verifyStoreData(channel, "BF2200");
483    }
484
485    @Test
486    public void testAuthenticateServer() {
487        int channel = mockLogicalChannelResponses("BF3802A0009000");
488
489        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
490        mEuiccCard.authenticateServer("A1B2C3-X4Y5Z6", // Matching id
491                Asn1Node.newBuilder(0xA0).build().toBytes(),
492                Asn1Node.newBuilder(0xA1).build().toBytes(),
493                Asn1Node.newBuilder(0xA2).build().toBytes(),
494                Asn1Node.newBuilder(0xA3).build().toBytes(), resultCaptor, mHandler);
495        resultCaptor.await();
496
497        assertUnexpectedException(resultCaptor.exception);
498        assertEquals("BF3802A000", IccUtils.bytesToHexString(resultCaptor.result));
499        verifyStoreData(channel,
500                "BF382D" + "A000" + "A100" + "A200" + "A300" + "A023"
501                        + "800D4131423243332D583459355A36" // Matching id
502                        + "A112800489674523" // TAC
503                        + "A100" // Device capabilities
504                        + "82088967452301214305"); // IMEI
505    }
506
507    @Test
508    public void testAuthenticateServer_Error() {
509        int channel = mockLogicalChannelResponses("BF38038101039000");
510
511        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
512        mEuiccCard.authenticateServer("A1B2C3-X4Y5Z6", // Matching id
513                Asn1Node.newBuilder(0xA0).build().toBytes(),
514                Asn1Node.newBuilder(0xA1).build().toBytes(),
515                Asn1Node.newBuilder(0xA2).build().toBytes(),
516                Asn1Node.newBuilder(0xA3).build().toBytes(), resultCaptor, mHandler);
517        resultCaptor.await();
518
519        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
520        verifyStoreData(channel,
521                "BF382D" + "A000" + "A100" + "A200" + "A300" + "A023"
522                        + "800D4131423243332D583459355A36" // Matching id
523                        + "A112800489674523" // TAC
524                        + "A100" // Device capabilities
525                        + "82088967452301214305"); // IMEI
526    }
527
528    @Test
529    public void testPrepareDownload() {
530        int channel = mockLogicalChannelResponses("BF2102A0009000");
531
532        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
533        mEuiccCard.prepareDownload(
534                IccUtils.hexStringToBytes("4131423243332D583459355A36"), // hashCc
535                Asn1Node.newBuilder(0xA0).build().toBytes(),
536                Asn1Node.newBuilder(0xA1).build().toBytes(),
537                Asn1Node.newBuilder(0xA2).build().toBytes(), resultCaptor, mHandler);
538        resultCaptor.await();
539
540        assertEquals("BF2102A000", IccUtils.bytesToHexString(resultCaptor.result));
541        verifyStoreData(channel,
542                "BF2115" + "A000" + "A100"
543                        + "040D4131423243332D583459355A36" // hashCc
544                        + "A200");
545    }
546
547    @Test
548    public void testPrepareDownload_Error() {
549        int channel = mockLogicalChannelResponses("BF2105A1030201039000");
550
551        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
552        mEuiccCard.prepareDownload(
553                IccUtils.hexStringToBytes("4131423243332D583459355A36"), // hashCc
554                Asn1Node.newBuilder(0xA0).build().toBytes(),
555                Asn1Node.newBuilder(0xA1).build().toBytes(),
556                Asn1Node.newBuilder(0xA2).build().toBytes(), resultCaptor, mHandler);
557        resultCaptor.await();
558
559        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
560        verifyStoreData(channel,
561                "BF2115" + "A000" + "A100"
562                        + "040D4131423243332D583459355A36" // hashCc
563                        + "A200");
564    }
565
566    @Test
567    public void testLoadBoundProfilePackage() {
568        int channel = mockLogicalChannelResponses(
569                // For boundProfilePackage head + initialiseSecureChannelRequest
570                // (ES8+.InitialiseSecureChannel)
571                "9000",
572                // For firstSequenceOf87 (ES8+.ConfigureISDP)
573                "9000",
574                // For head of sequenceOf88 (ES8+.StoreMetadata)
575                "9000",
576                // For body (element 1) of sequenceOf88 (ES8+.StoreMetadata)
577                "9000",
578                "9000",
579                // For head of sequenceOf86 (ES8+.LoadProfileElements)
580                "9000",
581                // For body (element 1) of sequenceOf86 (ES8+.LoadProfileElements)
582                "9000",
583                // Profile installation result (element 2 of sequenceOf86)
584                "BF37009000");
585
586        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
587        mEuiccCard.loadBoundProfilePackage(
588                Asn1Node.newBuilder(0xBF36)
589                        .addChild(Asn1Node.newBuilder(0xBF23))
590                        .addChild(Asn1Node.newBuilder(0xA0)
591                                .addChildAsBytes(0x87, new byte[] {1, 2, 3}))
592                        .addChild(Asn1Node.newBuilder(0xA1)
593                                .addChildAsBytes(0x88, new byte[] {4, 5, 6}))
594                        .addChild(Asn1Node.newBuilder(0xA2))
595                        .addChild(Asn1Node.newBuilder(0xA3)
596                                .addChildAsBytes(0x86, new byte[] {7, 8, 9})
597                                .addChildAsBytes(0x86, new byte[] {0xA, 0xB, 0xC}))
598                        .build().toBytes(),
599                resultCaptor, mHandler);
600        resultCaptor.await();
601
602        assertEquals("BF3700", IccUtils.bytesToHexString(resultCaptor.result));
603        verifyStoreData(channel, "BF361FBF2300"); // ES8+.InitialiseSecureChannel
604        verifyStoreData(channel, "A0058703010203"); // ES8+.ConfigureISDP
605        verifyStoreData(channel, "A105"); // ES8+.StoreMetadata
606        verifyStoreData(channel, "8803040506"); // ES8+.StoreMetadata
607        verifyStoreData(channel, "A200");
608        verifyStoreData(channel, "A30A"); // ES8+.LoadProfileElements
609        verifyStoreData(channel, "8603070809"); // ES8+.LoadProfileElements
610        verifyStoreData(channel, "86030A0B0C"); // ES8+.LoadProfileElements
611    }
612
613    @Test
614    public void testLoadBoundProfilePackage_Error() {
615        int channel = mockLogicalChannelResponses(
616                // For boundProfilePackage head + initialiseSecureChannelRequest
617                // (ES8+.InitialiseSecureChannel)
618                "9000",
619                // For firstSequenceOf87 (ES8+.ConfigureISDP)
620                "9000",
621                // For head of sequenceOf88 (ES8+.StoreMetadata)
622                "9000",
623                // For body (element 1) of sequenceOf88 (ES8+.StoreMetadata)
624                "9000",
625                "9000",
626                // For head of sequenceOf86 (ES8+.LoadProfileElements)
627                "9000",
628                // For body (element 1) of sequenceOf86 (ES8+.LoadProfileElements)
629                "9000",
630                // Profile installation result (element 2 of sequenceOf86)
631                "BF370ABF2707A205A1038101039000");
632
633        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
634        mEuiccCard.loadBoundProfilePackage(
635                Asn1Node.newBuilder(0xBF36)
636                        .addChild(Asn1Node.newBuilder(0xBF23))
637                        .addChild(Asn1Node.newBuilder(0xA0)
638                                .addChildAsBytes(0x87, new byte[] {1, 2, 3}))
639                        .addChild(Asn1Node.newBuilder(0xA1)
640                                .addChildAsBytes(0x88, new byte[] {4, 5, 6}))
641                        .addChild(Asn1Node.newBuilder(0xA2))
642                        .addChild(Asn1Node.newBuilder(0xA3)
643                                .addChildAsBytes(0x86, new byte[] {7, 8, 9})
644                                .addChildAsBytes(0x86, new byte[] {0xA, 0xB, 0xC}))
645                        .build().toBytes(),
646                resultCaptor, mHandler);
647        resultCaptor.await();
648
649        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
650        verifyStoreData(channel, "BF361FBF2300"); // ES8+.InitialiseSecureChannel
651        verifyStoreData(channel, "A0058703010203"); // ES8+.ConfigureISDP
652        verifyStoreData(channel, "A105"); // ES8+.StoreMetadata
653        verifyStoreData(channel, "8803040506"); // ES8+.StoreMetadata
654        verifyStoreData(channel, "A200");
655        verifyStoreData(channel, "A30A"); // ES8+.LoadProfileElements
656        verifyStoreData(channel, "8603070809"); // ES8+.LoadProfileElements
657        verifyStoreData(channel, "86030A0B0C"); // ES8+.LoadProfileElements
658    }
659
660    @Test
661    public void testCancelSession() {
662        int channel = mockLogicalChannelResponses("BF41009000");
663
664        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
665        mEuiccCard.cancelSession(IccUtils.hexStringToBytes("A1B2C3"),
666                EuiccCardManager.CANCEL_REASON_POSTPONED, resultCaptor, mHandler);
667        resultCaptor.await();
668
669        assertEquals("BF4100", IccUtils.bytesToHexString(resultCaptor.result));
670        verifyStoreData(channel, "BF41088003A1B2C3810101");
671    }
672
673    @Test
674    public void testCancelSession_Error() {
675        int channel = mockLogicalChannelResponses("BF41038101039000");
676
677        ResultCaptor<byte[]> resultCaptor = new ResultCaptor<>();
678        mEuiccCard.cancelSession(IccUtils.hexStringToBytes("A1B2C3"),
679                EuiccCardManager.CANCEL_REASON_POSTPONED, resultCaptor, mHandler);
680        resultCaptor.await();
681
682        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
683        verifyStoreData(channel, "BF41088003A1B2C3810101");
684    }
685
686    @Test
687    public void testListNotifications() {
688        int channel = mockLogicalChannelResponses("BF282BA029"
689                + "BF2F118001010C08736D64702E636F6D81020410" // Notification #1
690                + "BF2F128001020C09736D6470322E636F6D81020420" // Notification #2
691                + "9000");
692
693        ResultCaptor<EuiccNotification[]> resultCaptor = new ResultCaptor<>();
694        mEuiccCard.listNotifications(
695                EuiccNotification.EVENT_DELETE | EuiccNotification.EVENT_DISABLE,
696                resultCaptor, mHandler);
697        resultCaptor.await();
698
699        assertArrayEquals(
700                new EuiccNotification[] {
701                        new EuiccNotification(1, "smdp.com", EuiccNotification.EVENT_DELETE, null),
702                        new EuiccNotification(2, "smdp2.com", EuiccNotification.EVENT_DISABLE, null)
703                },
704                resultCaptor.result);
705        verifyStoreData(channel, "BF280481020430");
706    }
707
708    @Test
709    public void testListNotifications_Error() {
710        int channel = mockLogicalChannelResponses("BF28038101039000");
711
712        ResultCaptor<EuiccNotification[]> resultCaptor = new ResultCaptor<>();
713        mEuiccCard.listNotifications(
714                EuiccNotification.EVENT_DELETE | EuiccNotification.EVENT_DISABLE,
715                resultCaptor, mHandler);
716        resultCaptor.await();
717
718        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
719        verifyStoreData(channel, "BF280481020430");
720    }
721
722    @Test
723    public void testRetrieveNotificationList() {
724        int channel = mockLogicalChannelResponses("BF2B2FA02D"
725                // Notification #1
726                + "3014BF2F118001010C08736D64702E636F6D81020410"
727                // Notification #2
728                + "3015BF2F128001020C09736D6470322E636F6D81020420"
729                + "9000");
730
731        ResultCaptor<EuiccNotification[]> resultCaptor = new ResultCaptor<>();
732        mEuiccCard.retrieveNotificationList(
733                EuiccNotification.EVENT_DELETE | EuiccNotification.EVENT_DISABLE,
734                resultCaptor, mHandler);
735        resultCaptor.await();
736
737        assertArrayEquals(
738                new EuiccNotification[] {
739                        new EuiccNotification(1, "smdp.com", EuiccNotification.EVENT_DELETE,
740                                IccUtils.hexStringToBytes(
741                                        "3014BF2F118001010C08736D64702E636F6D81020410")),
742                        new EuiccNotification(2, "smdp2.com", EuiccNotification.EVENT_DISABLE,
743                                IccUtils.hexStringToBytes(
744                                        "3015BF2F128001020C09736D6470322E636F6D81020420"))
745                },
746                resultCaptor.result);
747        verifyStoreData(channel, "BF2B06A00481020430");
748    }
749
750    @Test
751    public void testRetrieveNotificationList_Empty() {
752        int channel = mockLogicalChannelResponses("BF2B038101019000");
753
754        ResultCaptor<EuiccNotification[]> resultCaptor = new ResultCaptor<>();
755        mEuiccCard.retrieveNotificationList(
756                EuiccNotification.EVENT_DELETE | EuiccNotification.EVENT_DISABLE,
757                resultCaptor, mHandler);
758        resultCaptor.await();
759
760        assertArrayEquals(new EuiccNotification[0], resultCaptor.result);
761        verifyStoreData(channel, "BF2B06A00481020430");
762    }
763
764    @Test
765    public void testRetrieveNotificationList_Error() {
766        int channel = mockLogicalChannelResponses("BF2B038101039000");
767
768        ResultCaptor<EuiccNotification[]> resultCaptor = new ResultCaptor<>();
769        mEuiccCard.retrieveNotificationList(
770                EuiccNotification.EVENT_DELETE | EuiccNotification.EVENT_DISABLE,
771                resultCaptor, mHandler);
772        resultCaptor.await();
773
774        assertEquals(3, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
775        verifyStoreData(channel, "BF2B06A00481020430");
776    }
777
778    @Test
779    public void testRetrieveNotification() {
780        int channel = mockLogicalChannelResponses("BF2B18A016"
781                + "3014BF2F118001010C08736D64702E636F6D81020410" // Notification
782                + "9000");
783
784        ResultCaptor<EuiccNotification> resultCaptor = new ResultCaptor<>();
785        mEuiccCard.retrieveNotification(5, resultCaptor, mHandler);
786        resultCaptor.await();
787
788        assertEquals(
789                new EuiccNotification(1, "smdp.com", EuiccNotification.EVENT_DELETE,
790                        IccUtils.hexStringToBytes("3014BF2F118001010C08736D64702E636F6D81020410")),
791                resultCaptor.result);
792        verifyStoreData(channel, "BF2B05A003800105");
793    }
794
795    @Test
796    public void testRetrieveNotification_Error() {
797        int channel = mockLogicalChannelResponses("BF2B038101019000");
798
799        ResultCaptor<EuiccNotification> resultCaptor = new ResultCaptor<>();
800        mEuiccCard.retrieveNotification(5, resultCaptor, mHandler);
801        resultCaptor.await();
802
803        assertEquals(1, ((EuiccCardErrorException) resultCaptor.exception).getErrorCode());
804        verifyStoreData(channel, "BF2B05A003800105");
805    }
806
807    @Test
808    public void testRemoveNotificationFromList() {
809        int channel = mockLogicalChannelResponses("BF30038001009000");
810
811        ResultCaptor<Void> resultCaptor = new ResultCaptor<>();
812        mEuiccCard.removeNotificationFromList(5, resultCaptor, mHandler);
813        resultCaptor.await();
814
815        assertUnexpectedException(resultCaptor.exception);
816        verifyStoreData(channel, "BF3003800105");
817    }
818
819    private void verifyStoreData(int channel, String command) {
820        verify(mMockCi, times(1))
821                .iccTransmitApduLogicalChannel(eq(channel), eq(0x80 | channel), eq(0xE2), eq(0x91),
822                        eq(0), eq(command.length() / 2), eq(command), any());
823    }
824
825    private int mockLogicalChannelResponses(Object... responses) {
826        int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi,
827                "E00582030200009000");
828        LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, responses);
829        LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
830        return channel;
831    }
832}
833