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