/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Contributed by Orange */

package android.omapi.cts;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;

import android.content.pm.PackageManager;
import android.os.Build;
import android.os.SystemProperties;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.PropertyUtil;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;

public class OmapiTest {

    private final static String UICC_READER_PREFIX = "SIM";
    private final static String ESE_READER_PREFIX = "eSE";
    private final static String SD_READER_PREFIX = "SD";
    private final static String OMAPI_VERSION = "3.3";
    private final static byte[] SELECTABLE_AID =
            new byte[]{(byte) 0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
                    0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31};
    private final static byte[] LONG_SELECT_RESPONSE_AID =
            new byte[]{(byte) 0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
                    0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x32};
    private final static byte[] NON_SELECTABLE_AID =
            new byte[]{(byte) 0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
                    0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, (byte) 0xFF};

    /* MANAGE open/close and SELECT AID */
    private final static byte[][] ILLEGAL_COMMANDS_TRANSMIT = new byte[][]{{0x00, 0x70, 0x00, 0x00},
            {0x00, 0x70, (byte) 0x80, 0x00},
            {0x00, (byte) 0xA4, 0x04, 0x04, 0x10, 0x4A, 0x53,
                    0x52, 0x31, 0x37, 0x37, 0x54, 0x65, 0x73,
                    0x74, 0x65, 0x72, 0x20, 0x31, 0x2E, 0x30}
    };

    /* OMAPI APDU Test case 1 and 3 */
    private final static byte[][] NO_DATA_APDU = new byte[][]{{0x00, 0x06, 0x00, 0x00},
            {(byte) 0x80, 0x06, 0x00, 0x00},
            {(byte) 0xA0, 0x06, 0x00, 0x00},
            {(byte) 0x94, 0x06, 0x00, 0x00},
            {0x00, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA},
            {(byte) 0x80, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA},
            {(byte) 0xA0, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA},
            {(byte) 0x94, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA}
    };
    /* OMAPI APDU Test case 2 and 4 */
    private final static byte[][] DATA_APDU = new byte[][]{{0x00, 0x08, 0x00, 0x00, 0x00},
            {(byte) 0x80, 0x08, 0x00, 0x00, 0x00},
            {(byte) 0xA0, 0x08, 0x00, 0x00, 0x00},
            {(byte) 0x94, 0x08, 0x00, 0x00, 0x00},
            {0x00, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00},
            {(byte) 0x80, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00},
            {(byte) 0xA0, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00},
            {(byte) 0x94, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00}
    };

    /* Case 2 APDU command expects the P2 received in the SELECT command as 1-byte outgoing data */
    private static final byte[] CHECK_SELECT_P2_APDU = new byte[] {
            0x00, (byte) 0xF4, 0x00, 0x00, 0x00
    };

    /* OMAPI APDU Test case 1 and 3 */
    private final static byte[][] SW_62xx_NO_DATA_APDU =
            new byte[][]{{0x00, (byte) 0xF3, 0x00, 0x06},
                    {0x00, (byte) 0xF3, 0x00, 0x0A, 0x01, (byte) 0xAA}
            };
    /* OMAPI APDU Test case 2 and 4 */
    private final static byte[] SW_62xx_DATA_APDU = new byte[]{0x00, (byte) 0xF3, 0x00, 0x08, 0x00};
    private final static byte[] SW_62xx_VALIDATE_DATA_APDU =
            new byte[]{0x00, (byte) 0xF3, 0x00, 0x0C, 0x01, (byte) 0xAA, 0x00};
    private final static byte[][] SW_62xx =
            new byte[][]{{0x62, 0x00}, {0x62, (byte) 0x81}, {0x62, (byte) 0x82},
                    {0x62, (byte) 0x83},
                    {0x62, (byte) 0x85}, {0x62, (byte) 0xF1}, {0x62, (byte) 0xF2},
                    {0x63, (byte) 0xF1},
                    {0x63, (byte) 0xF2}, {0x63, (byte) 0xC2}, {0x62, 0x02}, {0x62, (byte) 0x80},
                    {0x62, (byte) 0x84}, {0x62, (byte) 0x86}, {0x63, 0x00}, {0x63, (byte) 0x81}
            };
    private final static byte[][] SEGMENTED_RESP_APDU = new byte[][]{
            //Get response Case2 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
            {0x00, (byte) 0xC2, 0x08, 0x00, 0x00},
            //Get response Case4 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
            {0x00, (byte) 0xC4, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
            //Get response Case2 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
            {0x00, (byte) 0xC6, 0x08, 0x00, 0x00},
            //Get response Case4 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
            {0x00, (byte) 0xC8, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
            //Test device buffer capacity 7FFF data
            {0x00, (byte) 0xC2, (byte) 0x7F, (byte) 0xFF, 0x00},
            //Get response 6CFF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
            {0x00, (byte) 0xCF, 0x08, 0x00, 0x00},
            //Get response with another CLA  with answer length (P1P2) of 0x0800, 2048 bytes
            {(byte) 0x94, (byte) 0xC2, 0x08, 0x00, 0x00}
    };
    private final long SERVICE_CONNECTION_TIME_OUT = 3000;
    private SEService seService;
    private Object serviceMutex = new Object();
    private Timer connectionTimer;
    private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask();
    private boolean connected = false;
    private final OnConnectedListener mListener = new OnConnectedListener() {
                @Override
                public void onConnected() {
                    synchronized (serviceMutex) {
                        connected = true;
                        serviceMutex.notify();
                    }
                }
            };

    class SynchronousExecutor implements Executor {
        public void execute(Runnable r) {
            r.run();
        }
    }

    private boolean supportsHardware() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        boolean lowRamDevice = SystemProperties.getBoolean("ro.config.low_ram", false);
        return !lowRamDevice || pm.hasSystemFeature("android.hardware.type.watch")
                || hasSecureElementPackage(pm);
    }

    private boolean hasSecureElementPackage(PackageManager pm) {
        try {
            pm.getPackageInfo("com.android.se", 0 /* flags*/);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    private boolean supportUICCReaders() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_UICC);
    }

    private boolean supportESEReaders() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_ESE);
    }

    private boolean supportSDReaders() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_SD);
    }

    private boolean supportOMAPIReaders() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        return (pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_UICC)
            || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_ESE)
            || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_SD));
    }


    private void assertGreaterOrEqual(long greater, long lesser) {
        assertTrue("" + greater + " expected to be greater than or equal to " + lesser,
                greater >= lesser);
    }

    @Before
    public void setUp() throws Exception {
        assumeTrue(PropertyUtil.getFirstApiLevel() > Build.VERSION_CODES.O_MR1);
        assumeTrue(supportsHardware());
        seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
        connectionTimer = new Timer();
        connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
    }

    @After
    public void tearDown() throws Exception {
        if (seService != null && seService.isConnected()) {
            seService.shutdown();
            connected = false;
        }
    }

    private void waitForConnection() throws TimeoutException {
        synchronized (serviceMutex) {
            if (!connected) {
                try {
                    serviceMutex.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (!connected) {
                throw new TimeoutException(
                        "Service could not be connected after " + SERVICE_CONNECTION_TIME_OUT
                                + " ms");
            }
            if (connectionTimer != null) {
                connectionTimer.cancel();
            }
        }
    }

    /** Tests getReaders API */
    @Test
    public void testGetReaders() {
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            ArrayList<Reader> uiccReaders = new ArrayList<Reader>();
            ArrayList<Reader> eseReaders = new ArrayList<Reader>();
            ArrayList<Reader> sdReaders = new ArrayList<Reader>();

            for (Reader reader : readers) {
                assertTrue(reader.isSecureElementPresent());
                String name = reader.getName();
                if (!(name.startsWith(UICC_READER_PREFIX) || name.startsWith(ESE_READER_PREFIX)
                        || name.startsWith(SD_READER_PREFIX))) {
                    fail("Incorrect Reader name");
                }
                assertNotNull("getseService returned null", reader.getSEService());

                if (reader.getName().startsWith(UICC_READER_PREFIX)) {
                    uiccReaders.add(reader);
                }
                if (reader.getName().startsWith(ESE_READER_PREFIX)) {
                    eseReaders.add(reader);
                }
                if (reader.getName().startsWith(SD_READER_PREFIX)) {
                    sdReaders.add(reader);
                }
            }

            if (supportUICCReaders()) {
                assertGreaterOrEqual(uiccReaders.size(), 1);
                // Test API getUiccReader(int slotNumber)
                // The result should be the same as getReaders() with UICC reader prefix
                for (int i = 1; i <= uiccReaders.size(); i++) {
                    try {
                        Reader uiccReader = seService.getUiccReader(i);
                        if (!uiccReaders.contains(uiccReader))
                            fail("Incorrect reader object - getUiccReader(" + i + ")");
                    } catch (IllegalArgumentException e) {
                        fail("Fail to get Reader object by calling getUiccReader(" + i + ")");
                    }
                }
            } else {
                assertTrue(uiccReaders.size() == 0);
            }

            if (supportESEReaders()) {
                assertGreaterOrEqual(eseReaders.size(), 1);
            } else {
                assertTrue(eseReaders.size() == 0);
            }

            if (supportSDReaders()) {
                assertGreaterOrEqual(sdReaders.size(), 1);
            } else {
                assertTrue(sdReaders.size() == 0);
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    /** Tests getATR API */
    @Test
    public void testATR() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            ArrayList<Reader> uiccReaders = new ArrayList<Reader>();
            if (readers != null && readers.length > 0) {
                for (int i = 0; i < readers.length; i++) {
                    if (readers[i].getName().startsWith(UICC_READER_PREFIX)) {
                        uiccReaders.add(readers[i]);
                    }
                }

                for (Reader reader : uiccReaders) {
                    Session session = null;
                    try {
                        session = reader.openSession();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    assertNotNull("Could not open session", session);
                    byte[] atr = session.getATR();
                    session.close();
                    assertNotNull("ATR is Null", atr);
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    /** Tests OpenBasicChannel API when aid is null */
    @Test
    public void testOpenBasicChannelNullAid() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    session = reader.openSession();
                    assertNotNull("Could not open session", session);
                    channel = session.openBasicChannel(null, (byte) 0x00);
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
                if (reader.getName().startsWith(UICC_READER_PREFIX)) {
                    assertNull("Basic channel on UICC can be opened", channel);
                } else {
                    assertNotNull("Basic Channel cannot be opened", channel);
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    /** Tests OpenBasicChannel API when aid is provided */
    @Test
    public void testOpenBasicChannelNonNullAid() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    session = reader.openSession();
                    assertNotNull("Could not open session", session);
                    channel = session.openBasicChannel(SELECTABLE_AID, (byte) 0x00);
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
                if (reader.getName().startsWith(UICC_READER_PREFIX)) {
                    assertNull("Basic channel on UICC can be opened", channel);
                } else {
                    assertNotNull("Basic Channel cannot be opened", channel);
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    /** Tests Select API */
    @Test
    public void testSelectableAid() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                testSelectableAid(reader, SELECTABLE_AID);
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    @Test
    public void testLongSelectResponse() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                byte[] selectResponse = testSelectableAid(reader, LONG_SELECT_RESPONSE_AID);
                assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    private byte[] testSelectableAid(Reader reader, byte[] aid) throws IOException {
        byte[] selectResponse = null;
        Session session = null;
        Channel channel = null;
        try {
            assertTrue(reader.isSecureElementPresent());
            session = reader.openSession();
            assertNotNull("Null Session", session);
            channel = session.openLogicalChannel(aid, (byte) 0x00);
            assertNotNull("Null Channel", channel);
            selectResponse = channel.getSelectResponse();
        } finally {
            if (channel != null) channel.close();
            if (session != null) session.close();
        }
        assertNotNull("Null Select Response", selectResponse);
        assertGreaterOrEqual(selectResponse.length, 2);
        assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
        assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
        return selectResponse;
    }

    /** Tests if NoSuchElementException in Select */
    @Test
    public void testWrongAid() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                testNonSelectableAid(reader, NON_SELECTABLE_AID);
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    private void testNonSelectableAid(Reader reader, byte[] aid) throws IOException {
        Session session = null;
        Channel channel = null;
        try {
            assertTrue(reader.isSecureElementPresent());
            session = reader.openSession();
            assertNotNull("null session", session);
            channel = session.openLogicalChannel(aid, (byte) 0x00);
            fail("Exception expected for this test");
        } catch (NoSuchElementException e) {
            // Catch the expected exception here.
        } finally {
            if (channel != null) channel.close();
            if (session != null) session.close();
        }
    }

    /** Tests if Security Exception in Transmit */
    @Test
    public void testSecurityExceptionInTransmit() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("null session", session);
                    channel = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
                    assertNotNull("Null Channel", channel);
                    byte[] selectResponse = channel.getSelectResponse();
                    assertNotNull("Null Select Response", selectResponse);
                    assertGreaterOrEqual(selectResponse.length, 2);
                    assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
                    assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
                    for (byte[] cmd : ILLEGAL_COMMANDS_TRANSMIT) {
                        try {
                            byte[] response = channel.transmit(cmd);
                            fail("Exception expected for this test");
                        } catch (SecurityException e) {
                            // Catch the expected exception here.
                        }
                    }
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    private byte[] internalTransmitApdu(Reader reader, byte[] apdu) throws IOException {
        byte[] transmitResponse = null;
        Session session = null;
        Channel channel = null;
        try {
            assertTrue(reader.isSecureElementPresent());
            session = reader.openSession();
            assertNotNull("null session", session);
            channel = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
            assertNotNull("Null Channel", channel);
            byte[] selectResponse = channel.getSelectResponse();
            assertNotNull("Null Select Response", selectResponse);
            assertGreaterOrEqual(selectResponse.length, 2);
            transmitResponse = channel.transmit(apdu);
        } finally {
            if (channel != null) channel.close();
            if (session != null) session.close();
        }
        return transmitResponse;
    }

    private byte[] internalTransmitApduWithoutP2(Reader reader, byte[] apdu,
            boolean testLogicalChannel) throws IOException {
        byte[] transmitResponse = null;
        Session session = null;
        Channel channel = null;
        try {
            assertTrue(reader.isSecureElementPresent());
            session = reader.openSession();
            assertNotNull("null session", session);
            if (testLogicalChannel) {
                channel = session.openLogicalChannel(SELECTABLE_AID);
            } else {
                channel = session.openBasicChannel(SELECTABLE_AID);
            }
            assertNotNull("Null Channel", channel);
            byte[] selectResponse = channel.getSelectResponse();
            assertNotNull("Null Select Response", selectResponse);
            assertGreaterOrEqual(selectResponse.length, 2);
            transmitResponse = channel.transmit(apdu);
        } finally {
            if (channel != null) channel.close();
            if (session != null) session.close();
        }
        return transmitResponse;
    }

    /**
     * Tests Transmit API for all readers.
     *
     * Checks the return status and verifies the size of the
     * response.
     */
    @Test
    public void testTransmitApdu() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                for (byte[] apdu : NO_DATA_APDU) {
                    byte[] response = internalTransmitApdu(reader, apdu);
                    assertThat(response.length, is(2));
                    assertThat(response[response.length - 1] & 0xFF, is(0x00));
                    assertThat(response[response.length - 2] & 0xFF, is(0x90));
                }

                for (byte[] apdu : DATA_APDU) {
                    byte[] response = internalTransmitApdu(reader, apdu);
                    /* 256 byte data and 2 bytes of status word */
                    assertThat(response.length, is(258));
                    assertThat(response[response.length - 1] & 0xFF, is(0x00));
                    assertThat(response[response.length - 2] & 0xFF, is(0x90));
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /**
     * Tests if underlying implementations returns the correct Status Word
     *
     * TO verify that :
     * - the device does not modify the APDU sent to the Secure Element
     * - the warning code is properly received by the application layer as SW answer
     * - the verify that the application layer can fetch the additionnal data (when present)
     */
    @Test
    public void testStatusWordTransmit() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                for (byte[] apdu : SW_62xx_NO_DATA_APDU) {
                    for (byte i = 0x00; i < SW_62xx.length; i++) {
                        apdu[2] = (byte)(i+1);
                        byte[] response = internalTransmitApdu(reader, apdu);
                        byte[] SW = SW_62xx[i];
                        assertThat(response[response.length - 1], is(SW[1]));
                        assertThat(response[response.length - 2], is(SW[0]));
                    }
                }

                for (byte i = 0x00; i < SW_62xx.length; i++) {
                    byte[] apdu = SW_62xx_DATA_APDU;
                    apdu[2] = (byte)(i+1);
                    byte[] response = internalTransmitApdu(reader, apdu);
                    byte[] SW = SW_62xx[i];
                    assertGreaterOrEqual(response.length, 3);
                    assertThat(response[response.length - 1], is(SW[1]));
                    assertThat(response[response.length - 2], is(SW[0]));
                }

                for (byte i = 0x00; i < SW_62xx.length; i++) {
                    byte[] apdu = SW_62xx_VALIDATE_DATA_APDU;
                    apdu[2] = (byte)(i+1);
                    byte[] response = internalTransmitApdu(reader, apdu);
                    assertGreaterOrEqual(response.length, apdu.length + 2);
                    byte[] responseSubstring = Arrays.copyOfRange(response, 0, apdu.length);
                    // We should not care about which channel number is actually assigned.
                    responseSubstring[0] = apdu[0];
                    assertTrue(Arrays.equals(responseSubstring, apdu));
                    byte[] SW = SW_62xx[i];
                    assertThat(response[response.length - 1], is(SW[1]));
                    assertThat(response[response.length - 2], is(SW[0]));
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Test if the responses are segmented by the underlying implementation */
    @Test
    public void testSegmentedResponseTransmit() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                for (byte[] apdu : SEGMENTED_RESP_APDU) {
                    byte[] response = internalTransmitApdu(reader, apdu);
                    byte[] b = { 0x00, 0x00, apdu[2], apdu[3] };
                    ByteBuffer wrapped = ByteBuffer.wrap(b);
                    int expectedLength = wrapped.getInt();
                    assertThat(response.length, is(expectedLength + 2));
                    assertThat(response[response.length - 1] & 0xFF, is(0x00));
                    assertThat(response[response.length - 2] & 0xFF, is(0x90));
                    assertThat(response[response.length - 3] & 0xFF, is(0xFF));
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /**
     * Tests the P2 value of the select command.
     *
     * Verifies that the default P2 value (0x00) is not modified by the underlying implementation.
     */
    @Test
    @ApiTest(apis = {"android.se.omapi.Session#openBasicChannel",
            "android.se.omapi.Session#openLogicalChannel"})
    public void testP2Value() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                byte[] response = internalTransmitApduWithoutP2(reader, CHECK_SELECT_P2_APDU, true);
                assertGreaterOrEqual(response.length, 3);
                assertThat(response[response.length - 1] & 0xFF, is(0x00));
                assertThat(response[response.length - 2] & 0xFF, is(0x90));
                assertThat(response[response.length - 3] & 0xFF, is(0x00));

                // skip basic channel verification for UICC reader
                if (reader.getName().startsWith(UICC_READER_PREFIX)) {
                    continue;
                }
                response = internalTransmitApduWithoutP2(reader, CHECK_SELECT_P2_APDU, false);
                assertGreaterOrEqual(response.length, 3);
                assertThat(response[response.length - 1] & 0xFF, is(0x00));
                assertThat(response[response.length - 2] & 0xFF, is(0x90));
            }
        } catch (Exception e) {
          fail("unexpected exception " + e);
        }
    }

    /** Tests closeChannels API */
    @Test
    public void testCloseChannels() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channelA = null;
                Channel channelB = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("null session", session);
                    channelA = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
                    assertNotNull("Null Channel", channelA);
                    channelB = session.openLogicalChannel(LONG_SELECT_RESPONSE_AID, (byte) 0x00);
                    assertNotNull("Null Channel", channelB);
                    session.closeChannels();
                    assertFalse("channel is still open", channelA.isOpen());
                    assertFalse("channel is still open", channelB.isOpen());
                } finally {
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Tests SEService getVersion API */
    @Test
    @ApiTest(apis = "android.se.omapi.SEService#getVersion")
    public void testGetOmapiVersion() {
        try {
            waitForConnection();
            assertTrue("Unexpected OMAPI version", seService.getVersion().equals(OMAPI_VERSION));
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Tests Reader closeSession API */
    @Test
    @ApiTest(apis = {"android.se.omapi.Reader#closeSessions", "android.se.omapi.Session#isClosed"})
    public void testCloseSessions() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session sessionA = null;
                Session sessionB = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    sessionA = reader.openSession();
                    assertNotNull("null session", sessionA);
                    assertFalse("session is closed", sessionA.isClosed());

                    sessionB = reader.openSession();
                    assertNotNull("null session", sessionB);
                    assertFalse("session is closed", sessionB.isClosed());

                    sessionA.getReader().closeSessions();
                    assertTrue("session is still open", sessionA.isClosed());
                    assertTrue("session is still open", sessionB.isClosed());
                } finally {
                    if (sessionA != null) sessionA.close();
                    if (sessionB != null) sessionB.close();
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Tests Reader reset API */
    @Test
    @ApiTest(apis = "android.se.omapi.Reader#reset")
    public void testOmapiReaderReset() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                try {
                    reader.reset();
                    fail("reset function is not blocked by permission ");
                } catch (SecurityException e) {
                    // Catch the expected exception here
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Tests Channel getSession API */
    @Test
    @ApiTest(apis = {"android.se.omapi.Channel#getSession", "android.se.omapi.Session#isClosed",
            "android.se.omapi.Channel#isBasicChannel"})
    public void testGetSession() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    session = reader.openSession();
                    assertNotNull("Could not open session", session);
                    channel = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
                    assertFalse("channel is not LogicalChannel", channel.isBasicChannel());

                    channel.getSession().close();
                    assertTrue(session.isClosed());
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /** Tests Channel selectNext API */
    @Test
    @ApiTest(apis = "android.se.omapi.Channel#selectNext")
    public void testSelectNext() {
        assumeTrue(supportOMAPIReaders());
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();

            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    session = reader.openSession();
                    assertNotNull("Could not open session", session);
                    channel = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
                    // no further Applet exists with this AID
                    assertFalse(channel.selectNext());

                    // send APDU to check selected applet stays selected on this channel
                    for (byte[] apdu : NO_DATA_APDU) {
                        byte[] response = channel.transmit(apdu);
                        assertThat(response.length, is(2));
                        assertThat(response[response.length - 1] & 0xFF, is(0x00));
                        assertThat(response[response.length - 2] & 0xFF, is(0x90));
                    }
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("unexpected exception " + e);
        }
    }

    /**
     * Verifies TLV data
     * @param tlv
     * @return true if the data is tlv formatted, false otherwise
     */
    private static boolean verifyBerTlvData(byte[] tlv){
        if (tlv == null || tlv.length == 0) {
            throw new RuntimeException("Invalid tlv, null");
        }
        int i = 0;
        if ((tlv[i++] & 0x1F) == 0x1F) {
            // extra byte for TAG field
            i++;
        }

        int len = tlv[i++] & 0xFF;
        if (len > 127) {
            // more than 1 byte for length
            int bytesLength = len-128;
            len = 0;
            for(int j = bytesLength; j > 0; j--) {
                len += (len << 8) + (tlv[i++] & 0xFF);
            }
        }
        // Additional 2 bytes for the SW
        return (tlv.length == (i+len+2));
    }

    class ServiceConnectionTimerTask extends TimerTask {
        @Override
        public void run() {
            synchronized (serviceMutex) {
                serviceMutex.notifyAll();
            }
        }
    }
}
