/*
 * Copyright (C) 2017 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.
 */
/*
 * Copyright (c) 2015-2017, The Linux Foundation.
 */

/*
 * Contributed by: Giesecke & Devrient GmbH.
 */

package com.android.se;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.secure_element.V1_0.ISecureElement;
import android.hardware.secure_element.V1_0.ISecureElementHalCallback;
import android.hardware.secure_element.V1_0.LogicalChannelResponse;
import android.hardware.secure_element.V1_0.SecureElementStatus;
import android.os.Build;
import android.os.Handler;
import android.os.HwBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.se.omapi.ISecureElementListener;
import android.se.omapi.ISecureElementReader;
import android.se.omapi.ISecureElementSession;
import android.se.omapi.SEService;
import android.util.Log;

import com.android.se.SecureElementService.SecureElementSession;
import com.android.se.internal.ByteArrayConverter;
import com.android.se.security.AccessControlEnforcer;
import com.android.se.security.ChannelAccess;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;

/**
 * Each Terminal represents a Secure Element.
 * Communicates to the SE via SecureElement HAL.
 */
public class Terminal {

    private final String mTag;
    private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
    private final Object mLock = new Object();
    private final String mName;
    public boolean mIsConnected = false;
    private Context mContext;
    private boolean mDefaultApplicationSelectedOnBasicChannel = true;

    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
    private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000;
    private static final int EVENT_GET_HAL = 1;

    private ISecureElement mSEHal;
    private android.hardware.secure_element.V1_2.ISecureElement mSEHal12;

    /** For each Terminal there will be one AccessController object. */
    private AccessControlEnforcer mAccessControlEnforcer;

    private static final String SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION =
            "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";

    public static final byte[] ISD_R_AID =
            new byte[]{
                    (byte) 0xA0,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x05,
                    (byte) 0x59,
                    (byte) 0x10,
                    (byte) 0x10,
                    (byte) 0xFF,
                    (byte) 0xFF,
                    (byte) 0xFF,
                    (byte) 0xFF,
                    (byte) 0x89,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x01,
                    (byte) 0x00,
            };

    private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() {
        @Override
        public void onStateChange(boolean state) {
            stateChange(state, "");
        }
    };

    private android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub mHalCallback11 =
            new android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub() {
        @Override
        public void onStateChange_1_1(boolean state, String reason) {
            stateChange(state, reason);
        }

        public void onStateChange(boolean state) {
            return;
        }
    };

    private void stateChange(boolean state, String reason) {
        synchronized (mLock) {
            Log.i(mTag, "OnStateChange:" + state + " reason:" + reason);
            mIsConnected = state;
            if (!state) {
                if (mAccessControlEnforcer != null) {
                    mAccessControlEnforcer.reset();
                }
                SecureElementStatsLog.write(
                        SecureElementStatsLog.SE_STATE_CHANGED,
                        SecureElementStatsLog.SE_STATE_CHANGED__STATE__DISCONNECTED,
                        reason,
                        mName);
            } else {
                // If any logical channel in use is in the channel list, it should be closed
                // because the access control enfocer allowed to open it by checking the access
                // rules retrieved before. Now we are going to retrieve the rules again and
                // the new rules can be different from the previous ones.
                closeChannels();
                try {
                    initializeAccessControl();
                } catch (Exception e) {
                    // ignore
                }
                mDefaultApplicationSelectedOnBasicChannel = true;
                SecureElementStatsLog.write(
                        SecureElementStatsLog.SE_STATE_CHANGED,
                        SecureElementStatsLog.SE_STATE_CHANGED__STATE__CONNECTED,
                        reason,
                        mName);
            }
        }
    }

    class SecureElementDeathRecipient implements HwBinder.DeathRecipient {
        @Override
        public void serviceDied(long cookie) {
            Log.e(mTag, mName + " died");
            SecureElementStatsLog.write(
                    SecureElementStatsLog.SE_STATE_CHANGED,
                    SecureElementStatsLog.SE_STATE_CHANGED__STATE__HALCRASH,
                    "HALCRASH",
                    mName);
            synchronized (mLock) {
                mIsConnected = false;
                if (mAccessControlEnforcer != null) {
                    mAccessControlEnforcer.reset();
                }
            }
            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0),
                    GET_SERVICE_DELAY_MILLIS);
        }
    }

    private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient();

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case EVENT_GET_HAL:
                    try {
                        initialize(true);
                    } catch (Exception e) {
                        Log.e(mTag, mName + " could not be initialized again");
                        sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0),
                                GET_SERVICE_DELAY_MILLIS);
                    }
                    break;
                default:
                    break;
            }
        }
    };

    public Terminal(String name, Context context) {
        mContext = context;
        mName = name;
        mTag = "SecureElement-Terminal-" + getName();
    }

    /**
     * Initializes the terminal
     *
     * @throws NoSuchElementException if there is no HAL implementation for the specified SE name
     * @throws RemoteException if there is a failure communicating with the remote
     */
    public void initialize(boolean retryOnFail) throws NoSuchElementException, RemoteException {
        android.hardware.secure_element.V1_1.ISecureElement mSEHal11 = null;
        synchronized (mLock) {
            try {
                mSEHal = mSEHal11 = mSEHal12 =
                        android.hardware.secure_element.V1_2.ISecureElement.getService(mName,
                                                                                       retryOnFail);
            } catch (Exception e) {
                Log.d(mTag, "SE Hal V1.2 is not supported");
            }
            if (mSEHal12 == null) {
                try {
                    mSEHal = mSEHal11 =
                            android.hardware.secure_element.V1_1.ISecureElement.getService(mName,
                                    retryOnFail);
                } catch (Exception e) {
                    Log.d(mTag, "SE Hal V1.1 is not supported");
                }

                if (mSEHal11 == null) {
                    mSEHal = ISecureElement.getService(mName, retryOnFail);
                    if (mSEHal == null) {
                        throw new NoSuchElementException("No HAL is provided for " + mName);
                    }
                }
            }
            if (mSEHal11 != null || mSEHal12 != null) {
                mSEHal11.init_1_1(mHalCallback11);
            } else {
                mSEHal.init(mHalCallback);
            }
            mSEHal.linkToDeath(mDeathRecipient, 0);
        }
        Log.i(mTag, mName + " was initialized");
        SecureElementStatsLog.write(
                SecureElementStatsLog.SE_STATE_CHANGED,
                SecureElementStatsLog.SE_STATE_CHANGED__STATE__INITIALIZED,
                "INIT",
                mName);
    }

    private ArrayList<Byte> byteArrayToArrayList(byte[] array) {
        ArrayList<Byte> list = new ArrayList<Byte>();
        if (array == null) {
            return list;
        }

        for (Byte b : array) {
            list.add(b);
        }
        return list;
    }

    private byte[] arrayListToByteArray(ArrayList<Byte> list) {
        Byte[] byteArray = list.toArray(new Byte[list.size()]);
        int i = 0;
        byte[] result = new byte[list.size()];
        for (Byte b : byteArray) {
            result[i++] = b.byteValue();
        }
        return result;
    }

    /**
     * Closes the given channel
     */
    public void closeChannel(Channel channel) {
        if (channel == null) {
            return;
        }
        synchronized (mLock) {
            if (mIsConnected) {
                try {
                    byte status = mSEHal.closeChannel((byte) channel.getChannelNumber());
                    /* For Basic Channels, errors are expected.
                     * Underlying implementations use this call as an indication when there
                     * aren't any users actively using the channel, and the chip can go
                     * into low power state.
                     */
                    if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) {
                        Log.e(mTag, "Error closing channel " + channel.getChannelNumber());
                    }
                } catch (RemoteException e) {
                    Log.e(mTag, "Exception in closeChannel() " + e);
                }
            }
            mChannels.remove(channel.getChannelNumber(), channel);
            if (mChannels.get(channel.getChannelNumber()) != null) {
                Log.e(mTag, "Removing channel failed");
            }
        }
    }

    /**
     * Cleans up all the channels in use.
     */
    public synchronized void closeChannels() {
        Collection<Channel> col = mChannels.values();
        Channel[] channelList = col.toArray(new Channel[col.size()]);
        for (Channel channel : channelList) {
            channel.close();
        }
    }

    /**
     * Closes the terminal.
     */
    public void close() {
        synchronized (mLock) {
            if (mSEHal != null) {
                try {
                    mSEHal.unlinkToDeath(mDeathRecipient);
                } catch (RemoteException e) {
                    // ignore
                }
            }
        }
    }

    public String getName() {
        return mName;
    }

    /**
     * Returns the ATR of the Secure Element, or null if not available.
     */
    public byte[] getAtr() {
        if (!mIsConnected) {
            return null;
        }

        try {
            ArrayList<Byte> responseList = mSEHal.getAtr();
            if (responseList.isEmpty()) {
                return null;
            }
            byte[] atr = arrayListToByteArray(responseList);
            if (DEBUG) {
                Log.i(mTag, "ATR : " + ByteArrayConverter.byteArrayToHexString(atr));
            }
            return atr;
        } catch (RemoteException e) {
            Log.e(mTag, "Exception in getAtr()" + e);
            return null;
        }
    }

    /**
     * Selects the default application on the basic channel.
     *
     * If there is an exception selecting the default application, select
     * is performed with the default access control aid.
     */
    public void selectDefaultApplication() {
        try {
            select(null);
        } catch (NoSuchElementException e) {
            if (getAccessControlEnforcer() != null) {
                try {
                    select(mAccessControlEnforcer.getDefaultAccessControlAid());
                } catch (Exception ignore) {
                }
            }
        } catch (Exception ignore) {
        }
    }

    private void select(byte[] aid) throws IOException {
        int commandSize = (aid == null ? 0 : aid.length) + 5;
        byte[] selectCommand = new byte[commandSize];
        selectCommand[0] = 0x00;
        selectCommand[1] = (byte) 0xA4;
        selectCommand[2] = 0x04;
        selectCommand[3] = 0x00;
        if (aid != null && aid.length != 0) {
            selectCommand[4] = (byte) aid.length;
            System.arraycopy(aid, 0, selectCommand, 5, aid.length);
        } else {
            selectCommand[4] = 0x00;
        }
        byte[] selectResponse = transmit(selectCommand);
        if (selectResponse.length < 2) {
            selectResponse = null;
            throw new NoSuchElementException("Response length is too small");
        }
        int sw1 = selectResponse[selectResponse.length - 2] & 0xFF;
        int sw2 = selectResponse[selectResponse.length - 1] & 0xFF;
        if (sw1 != 0x90 || sw2 != 0x00) {
            selectResponse = null;
            throw new NoSuchElementException("Status word is incorrect");
        }
    }

    /**
     * Opens a Basic Channel with the given AID and P2 paramters
     */
    public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2,
            ISecureElementListener listener, String packageName, int pid) throws IOException,
            NoSuchElementException {
        if (aid != null && aid.length == 0) {
            aid = null;
        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
            throw new IllegalArgumentException("AID out of range");
        } else if (!mIsConnected) {
            throw new IOException("Secure Element is not connected");
        }

        ChannelAccess channelAccess = null;
        if (packageName != null) {
            Log.w(mTag, "Enable access control on basic channel for " + packageName);
            SecureElementStatsLog.write(
                    SecureElementStatsLog.SE_OMAPI_REPORTED,
                    SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL,
                    mName,
                    packageName);
            try {
                // For application without privilege permission or carrier privilege,
                // openBasicChannel with UICC terminals should be rejected.
                channelAccess = setUpChannelAccess(aid, packageName, pid, true);
            } catch (MissingResourceException e) {
                return null;
            }
        }

        synchronized (mLock) {
            if (mChannels.get(0) != null) {
                Log.e(mTag, "basic channel in use");
                return null;
            }
            if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) {
                Log.e(mTag, "default application is not selected");
                return null;
            }

            ArrayList<byte[]> responseList = new ArrayList<byte[]>();
            byte[] status = new byte[1];

            try {
                mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
                        new ISecureElement.openBasicChannelCallback() {
                            @Override
                            public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
                                status[0] = halStatus;
                                responseList.add(arrayListToByteArray(responseObject));
                                return;
                            }
                        });
            } catch (RemoteException e) {
                throw new IOException(e.getMessage());
            }

            byte[] selectResponse = responseList.get(0);
            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
                return null;
            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
                throw new UnsupportedOperationException("OpenBasicChannel() failed");
            } else if (status[0] == SecureElementStatus.IOERROR) {
                throw new IOException("OpenBasicChannel() failed");
            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
                throw new NoSuchElementException("OpenBasicChannel() failed");
            }

            Channel basicChannel = new Channel(session, this, 0, selectResponse, aid,
                    listener);
            basicChannel.setChannelAccess(channelAccess);

            if (aid != null) {
                mDefaultApplicationSelectedOnBasicChannel = false;
            }
            mChannels.put(0, basicChannel);
            return basicChannel;
        }
    }

    /**
     * Opens a logical Channel without Channel Access initialization.
     */
    public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException,
            NoSuchElementException {
        return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0);
    }

    /**
     * Opens a logical Channel with AID.
     */
    public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2,
            ISecureElementListener listener, String packageName, int pid) throws IOException,
            NoSuchElementException {
        if (aid != null && aid.length == 0) {
            aid = null;
        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
            throw new IllegalArgumentException("AID out of range");
        } else if (!mIsConnected) {
            throw new IOException("Secure Element is not connected");
        }

        ChannelAccess channelAccess = null;
        if (packageName != null) {
            Log.w(mTag, "Enable access control on logical channel for " + packageName);
            SecureElementStatsLog.write(
                    SecureElementStatsLog.SE_OMAPI_REPORTED,
                    SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL,
                    mName,
                    packageName);
            try {
                channelAccess = setUpChannelAccess(aid, packageName, pid, false);
            } catch (MissingResourceException | UnsupportedOperationException e) {
                return null;
            }
        }

        synchronized (mLock) {
            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
            byte[] status = new byte[1];

            try {
                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
                        new ISecureElement.openLogicalChannelCallback() {
                            @Override
                            public void onValues(LogicalChannelResponse response, byte halStatus) {
                                status[0] = halStatus;
                                responseArray[0] = response;
                                return;
                            }
                        });
            } catch (RemoteException e) {
                throw new IOException(e.getMessage());
            }

            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
                return null;
            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
                throw new UnsupportedOperationException("OpenLogicalChannel() failed");
            } else if (status[0] == SecureElementStatus.IOERROR) {
                throw new IOException("OpenLogicalChannel() failed");
            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
                throw new NoSuchElementException("OpenLogicalChannel() failed");
            }
            if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) {
                return null;
            }
            int channelNumber = responseArray[0].channelNumber;
            byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse);
            Channel logicalChannel = new Channel(session, this, channelNumber,
                    selectResponse, aid, listener);
            logicalChannel.setChannelAccess(channelAccess);

            mChannels.put(channelNumber, logicalChannel);
            return logicalChannel;
        }
    }

    /**
     * Returns true if the given AID can be selected on the Terminal
     */
    public boolean isAidSelectable(byte[] aid) {
        if (aid == null) {
            throw new NullPointerException("aid must not be null");
        } else if (!mIsConnected) {
            Log.e(mTag, "Secure Element is not connected");
            return false;
        }

        synchronized (mLock) {
            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
            byte[] status = new byte[1];
            try {
                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00,
                        new ISecureElement.openLogicalChannelCallback() {
                            @Override
                            public void onValues(LogicalChannelResponse response, byte halStatus) {
                                status[0] = halStatus;
                                responseArray[0] = response;
                                return;
                            }
                        });
                if (status[0] == SecureElementStatus.SUCCESS) {
                    mSEHal.closeChannel(responseArray[0].channelNumber);
                    return true;
                }
                return false;
            } catch (RemoteException e) {
                Log.e(mTag, "Error in isAidSelectable() returning false" + e);
                return false;
            }
        }
    }

    /**
     * Transmits the specified command and returns the response.
     *
     * @param cmd the command APDU to be transmitted.
     * @return the response received.
     */
    public byte[] transmit(byte[] cmd) throws IOException {
        if (!mIsConnected) {
            Log.e(mTag, "Secure Element is not connected");
            throw new IOException("Secure Element is not connected");
        }

        byte[] rsp = transmitInternal(cmd);
        int sw1 = rsp[rsp.length - 2] & 0xFF;
        int sw2 = rsp[rsp.length - 1] & 0xFF;

        if (sw1 == 0x6C) {
            cmd[cmd.length - 1] = rsp[rsp.length - 1];
            rsp = transmit(cmd);
        } else if (sw1 == 0x61) {
            do {
                byte[] getResponseCmd = new byte[]{
                        cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2
                };
                byte[] tmp = transmitInternal(getResponseCmd);
                byte[] aux = rsp;
                rsp = new byte[aux.length + tmp.length - 2];
                System.arraycopy(aux, 0, rsp, 0, aux.length - 2);
                System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length);
                sw1 = rsp[rsp.length - 2] & 0xFF;
                sw2 = rsp[rsp.length - 1] & 0xFF;
            } while (sw1 == 0x61);
        }
        return rsp;
    }

    private byte[] transmitInternal(byte[] cmd) throws IOException {
        ArrayList<Byte> response;
        try {
            response = mSEHal.transmit(byteArrayToArrayList(cmd));
        } catch (RemoteException e) {
            throw new IOException(e.getMessage());
        }
        if (response.isEmpty()) {
            throw new IOException("Error in transmit()");
        }
        byte[] rsp = arrayListToByteArray(response);
        if (DEBUG) {
            Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd));
            Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp));
        }
        return rsp;
    }

    /**
     * Checks if the application is authorized to receive the transaction event.
     */
    public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid,
            String[] packageNames) {
        // Attempt to initialize the access control enforcer if it failed in the previous attempt
        // due to a kind of temporary failure or no rule was found.
        if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
            try {
                initializeAccessControl();
                // Just finished to initialize the access control enforcer.
                // It is too much to check the refresh tag in this case.
            } catch (Exception e) {
                Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
                return null;
            }
        }
        mAccessControlEnforcer.setPackageManager(packageManager);

        synchronized (mLock) {
            try {
                return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames);
            } catch (Exception e) {
                Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
                return null;
            }
        }
    }

    /**
     * Returns true if the Secure Element is present
     */
    public boolean isSecureElementPresent() {
        try {
            return mSEHal.isCardPresent();
        } catch (RemoteException e) {
            Log.e(mTag, "Error in isSecureElementPresent() " + e);
            return false;
        }
    }

    /**
     * Reset the Secure Element. Return true if success, false otherwise.
     */
    public boolean reset() {
        if (mSEHal12 == null) {
            return false;
        }
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION,
                "Need SECURE_ELEMENT_PRIVILEGED_OPERATION permission");

        try {
            byte status = mSEHal12.reset();
            // Successfully trigger reset. HAL service should send onStateChange
            // after secure element reset and initialization process complete
            if (status == SecureElementStatus.SUCCESS) {
                return true;
            }
            Log.e(mTag, "Error reseting terminal " + mName);
        } catch (RemoteException e) {
            Log.e(mTag, "Exception in reset()" + e);
        }
        return false;
    }

    /**
     * Initialize the Access Control and set up the channel access.
     */
    private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid,
            boolean isBasicChannel) throws IOException, MissingResourceException {
        boolean checkRefreshTag = true;
        if (isPrivilegedApplication(packageName)) {
            return ChannelAccess.getPrivilegeAccess(packageName, pid);
        }
        // Attempt to initialize the access control enforcer if it failed
        // due to a kind of temporary failure or no rule was found in the previous attempt.
        // For privilege access, do not attempt to initialize the access control enforcer
        // if no rule was found in the previous attempt.
        if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
            initializeAccessControl();
            // Just finished to initialize the access control enforcer.
            // It is too much to check the refresh tag in this case.
            checkRefreshTag = false;
        }
        mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());

        // Check carrier privilege when AID is not ISD-R
        if (getName().startsWith(SecureElementService.UICC_TERMINAL)
                && !Arrays.equals(aid, ISD_R_AID)) {
            try {
                PackageManager pm = mContext.getPackageManager();
                if (pm != null) {
                    PackageInfo pkgInfo =
                            pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
                    // Do not check the refresh tag for carrier privilege
                    if (mAccessControlEnforcer.checkCarrierPrivilege(pkgInfo, false)) {
                        Log.i(mTag, "setUp PrivilegeAccess for CarrierPrivilegeApplication. ");
                        return ChannelAccess.getCarrierPrivilegeAccess(packageName, pid);
                    }
                }
            } catch (NameNotFoundException ne) {
                Log.e(mTag, "checkCarrierPrivilege(): packageInfo is not found. ");
            } catch (Exception e) {
                Log.e(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage());
            }
            if (isBasicChannel) {
                throw new MissingResourceException("openBasicChannel is not allowed.", "", "");
            } else if (aid == null) {
                // openLogicalChannel with null aid is only allowed for privilege applications
                throw new UnsupportedOperationException(
                        "null aid is not accepted in UICC terminal.");
            }
        }

        synchronized (mLock) {
            try {
                ChannelAccess channelAccess =
                        mAccessControlEnforcer.setUpChannelAccess(aid, packageName,
                                checkRefreshTag);
                channelAccess.setCallingPid(pid);
                return channelAccess;
            } catch (IOException | MissingResourceException e) {
                throw e;
            } catch (Exception e) {
                throw new SecurityException("Exception in setUpChannelAccess()" + e);
            }
        }
    }

    /**
     * Initializes the Access Control for this Terminal
     */
    private synchronized void initializeAccessControl() throws IOException,
            MissingResourceException {
        synchronized (mLock) {
            if (mAccessControlEnforcer == null) {
                mAccessControlEnforcer = new AccessControlEnforcer(this);
            }
            try {
                mAccessControlEnforcer.initialize();
            } catch (IOException | MissingResourceException e) {
                // Retrieving access rules failed because of an IO error happened between
                // the terminal and the secure element or the lack of a logical channel available.
                // It might be a temporary failure, so the terminal shall attempt to cache
                // the access rules again later.
                mAccessControlEnforcer = null;
                throw e;
            }
        }
    }

    /**
     * Checks if Secure Element Privilege permission exists for the given package
     */
    private boolean isPrivilegedApplication(String packageName) {
        PackageManager pm = mContext.getPackageManager();
        if (pm != null) {
            return (pm.checkPermission(SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION,
                    packageName) == PackageManager.PERMISSION_GRANTED);
        }
        return false;
    }

    public AccessControlEnforcer getAccessControlEnforcer() {
        return mAccessControlEnforcer;
    }

    public Context getContext() {
        return mContext;
    }

    /**
     * Checks if Carrier Privilege exists for the given package
     */
    public boolean checkCarrierPrivilegeRules(PackageInfo pInfo) {
        boolean checkRefreshTag = true;
        if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
            try {
                initializeAccessControl();
            } catch (IOException e) {
                return false;
            }
            checkRefreshTag = false;
        }
        mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());

        synchronized (mLock) {
            try {
                return mAccessControlEnforcer.checkCarrierPrivilege(pInfo, checkRefreshTag);
            } catch (Exception e) {
                Log.i(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage());
                return false;
            }
        }
    }

    /** Dump data for debug purpose . */
    public void dump(PrintWriter writer) {
        writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName);
        writer.println();

        writer.println("mIsConnected:" + mIsConnected);
        writer.println();

        /* Dump the list of currunlty openned channels */
        writer.println("List of open channels:");

        for (Channel channel : mChannels.values()) {
            writer.println("channel " + channel.getChannelNumber() + ": ");
            writer.println("package: " + channel.getChannelAccess().getPackageName());
            writer.println("pid: " + channel.getChannelAccess().getCallingPid());
            writer.println("aid selected: " + channel.hasSelectedAid());
            writer.println("basic channel: " + channel.isBasicChannel());
            writer.println();
        }
        writer.println();

        /* Dump ACE data */
        if (mAccessControlEnforcer != null) {
            mAccessControlEnforcer.dump(writer);
        }
    }

    // Implementation of the SecureElement Reader interface according to OMAPI.
    final class SecureElementReader extends ISecureElementReader.Stub {

        private final SecureElementService mService;
        private final ArrayList<SecureElementSession> mSessions =
                new ArrayList<SecureElementSession>();

        SecureElementReader(SecureElementService service) {
            mService = service;
        }

        public byte[] getAtr() {
            return Terminal.this.getAtr();
        }

        @Override
        public boolean isSecureElementPresent() throws RemoteException {
            return Terminal.this.isSecureElementPresent();
        }

        @Override
        public void closeSessions() {
            synchronized (mLock) {
                while (mSessions.size() > 0) {
                    try {
                        mSessions.get(0).close();
                    } catch (Exception ignore) {
                    }
                }
                mSessions.clear();
            }
        }

        public void removeSession(SecureElementSession session) {
            if (session == null) {
                throw new NullPointerException("session is null");
            }
            mSessions.remove(session);
            synchronized (mLock) {
                if (mSessions.size() == 0) {
                    mDefaultApplicationSelectedOnBasicChannel = true;
                }
            }
        }

        @Override
        public ISecureElementSession openSession() throws RemoteException {
            if (!isSecureElementPresent()) {
                throw new ServiceSpecificException(SEService.IO_ERROR,
                        "Secure Element is not present.");
            }

            synchronized (mLock) {
                SecureElementSession session = mService.new SecureElementSession(this);
                mSessions.add(session);
                return session;
            }
        }

        Terminal getTerminal() {
            return Terminal.this;
        }

        @Override
        public boolean reset() {
            return Terminal.this.reset();
        }
    }
}
