Terminal.java revision 3878ce67ae4810258882c749f4dcbf508e6ad9ed
1ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/*
2ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Copyright (C) 2017 The Android Open Source Project
3ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue *
4ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Licensed under the Apache License, Version 2.0 (the "License");
5ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * you may not use this file except in compliance with the License.
6ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * You may obtain a copy of the License at
7ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue *
8ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue *      http://www.apache.org/licenses/LICENSE-2.0
9ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue *
10ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Unless required by applicable law or agreed to in writing, software
11ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * distributed under the License is distributed on an "AS IS" BASIS,
12ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * See the License for the specific language governing permissions and
14ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * limitations under the License.
15ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
16ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/*
17ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Copyright (c) 2015-2017, The Linux Foundation.
18ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
19ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
20ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/*
21ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Contributed by: Giesecke & Devrient GmbH.
22ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
23ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
24ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepackage com.android.se;
25ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
26ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.Context;
27ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.pm.PackageManager;
28ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.ISecureElement;
29ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.ISecureElementHalCallback;
30ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.LogicalChannelResponse;
31ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.SecureElementStatus;
32ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException;
33ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceSpecificException;
34ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener;
35ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader;
36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession;
37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.SEService;
38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log;
39ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.SecureElementService.SecureElementSession;
41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.internal.ByteArrayConverter;
42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.AccessControlEnforcer;
43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.ChannelAccess;
44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
453e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException;
46ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter;
47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList;
48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Collection;
49ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.HashMap;
50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Map;
51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException;
52ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/**
54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Each Terminal represents a Secure Element.
55ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Communicates to the SE via SecureElement HAL.
56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic class Terminal {
58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final String mTag;
60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final Object mLock = new Object();
62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final String mName;
63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean mIsConnected = false;
64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private Context mContext;
65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private boolean mDefaultApplicationSelectedOnBasicChannel = true;
66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private boolean mDebug = true;
68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
69ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ISecureElement mSEHal;
70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /** For each Terminal there will be one AccessController object. */
72ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private AccessControlEnforcer mAccessControlEnforcer;
73ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
74ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() {
75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void onStateChange(boolean state) {
77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "OnStateChange:" + state);
79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mIsConnected = state;
80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (!state) {
81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (mAccessControlEnforcer != null) {
82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mAccessControlEnforcer.reset();
83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } else {
85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    initializeAccessControl();
86e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    synchronized (mLock) {
87e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                        mDefaultApplicationSelectedOnBasicChannel = true;
88e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    }
89ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
90ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
91ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
92ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    };
93ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
94ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public Terminal(String name, Context context, ISecureElement seHal) {
95ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (seHal == null) {
96ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("ISecureElement cannot be null ");
97ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
98ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mContext = context;
99ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mName = name;
100ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mTag = "SecureElement-Terminal-" + getName();
101ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mSEHal = seHal;
102ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            seHal.init(mHalCallback);
104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
108ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ArrayList<Byte> byteArrayToArrayList(byte[] array) {
109ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ArrayList<Byte> list = new ArrayList<Byte>();
110ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (array == null) {
111ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return list;
112ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
113ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
114ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Byte b : array) {
115ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            list.add(b);
116ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
117ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return list;
118ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
119ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
120ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private byte[] arrayListToByteArray(ArrayList<Byte> list) {
121ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Byte[] byteArray = list.toArray(new Byte[list.size()]);
122ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int i = 0;
123ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] result = new byte[list.size()];
124ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Byte b : byteArray) {
125ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            result[i++] = b.byteValue();
126ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
127ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return result;
128ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
129ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
130ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
131ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Closes the given channel
132ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
133ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void closeChannel(Channel channel) {
134ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (channel == null) {
135ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return;
136ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
137ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mIsConnected && !channel.isBasicChannel()) {
138ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
139ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte status = mSEHal.closeChannel((byte) channel.getChannelNumber());
140ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (status != SecureElementStatus.SUCCESS) {
141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    Log.e(mTag, "Error closing channel " + channel.getChannelNumber());
142ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
143ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (RemoteException e) {
144ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Exception in closeChannel() " + e);
145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
146ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
147ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
148ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.remove(channel.getChannelNumber(), channel);
149ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mChannels.get(channel.getChannelNumber()) != null) {
150ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Removing channel failed");
151ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
152ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
153ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
154ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
155ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
156ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * This method is called in SecureElementService:onDestroy to clean up
157ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * all open channels.
158ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
159ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public synchronized void closeChannels() {
160ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Collection<Channel> col = mChannels.values();
161ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Channel[] channelList = col.toArray(new Channel[col.size()]);
162ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Channel channel : channelList) {
163ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            closeChannel(channel);
164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
165ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public String getName() {
168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return mName;
169ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns the ATR of the Secure Element, or null if not available.
173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public byte[] getAtr() {
175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (!mIsConnected) {
176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return null;
177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            ArrayList<Byte> responseList = mSEHal.getAtr();
181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (responseList.isEmpty()) {
182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return arrayListToByteArray(responseList);
185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Exception in getAtr()" + e);
187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return null;
188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Selects the default application on the basic channel.
193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     *
194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * If there is an exception selecting the default application, select
195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * is performed with the default access control aid.
196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
197ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void selectDefaultApplication() {
198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            select(null);
200ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (NoSuchElementException e) {
201ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (getAccessControlEnforcer() != null) {
202ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                try {
203ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    select(mAccessControlEnforcer.getDefaultAccessControlAid());
204ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } catch (Exception ignore) {
205ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
2073878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        } catch (Exception ignore) {
208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
2113878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    private void select(byte[] aid) throws IOException {
212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int commandSize = (aid == null ? 0 : aid.length) + 5;
213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectCommand = new byte[commandSize];
214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[0] = 0x00;
215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[1] = (byte) 0xA4;
216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[2] = 0x04;
217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[3] = 0x00;
218ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length != 0) {
219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectCommand[4] = (byte) aid.length;
220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            System.arraycopy(aid, 0, selectCommand, 5, aid.length);
221ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else {
222ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectCommand[4] = 0x00;
223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectResponse = transmit(selectCommand);
225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (selectResponse.length < 2) {
226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectResponse = null;
227ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NoSuchElementException("Response length is too small");
228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
229e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi        int sw1 = selectResponse[selectResponse.length - 2] & 0xFF;
230e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi        int sw2 = selectResponse[selectResponse.length - 1] & 0xFF;
231ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (sw1 != 0x90 || sw2 != 0x00) {
232ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectResponse = null;
233ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NoSuchElementException("Status word is incorrect");
234ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
235ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
236ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
237ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
238ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a Basic Channel with the given AID and P2 paramters
239ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
240ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2,
2413e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            ISecureElementListener listener, String packageName, int pid) throws IOException {
242ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length == 0) {
243ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            aid = null;
244ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
245ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("AID out of range");
2463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka        } else if (!mIsConnected) {
2473e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            throw new IOException("Secure Element is not connected");
248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Log.w(mTag, "Enable access control on basic channel for " + packageName);
251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ChannelAccess channelAccess = setUpChannelAccess(aid, packageName, true, pid);
252ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
253ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mChannels.get(0) != null) {
255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "basic channel in use");
256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
257ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
258ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) {
259ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "default application is not selected");
260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
263ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            ArrayList<byte[]> responseList = new ArrayList<byte[]>();
264ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
2653e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
2663e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
2673e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
2683e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        new ISecureElement.openBasicChannelCallback() {
2693e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            @Override
2703e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
2713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                status[0] = halStatus;
2723e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                responseList.add(arrayListToByteArray(responseObject));
2733e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                return;
2743e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            }
2753e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        });
2763e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (RemoteException e) {
2773e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException(e.getMessage());
2783e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
2793e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectResponse = responseList.get(0);
281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
282ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
283ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
284ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("OpenBasicChannel() failed");
285ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.IOERROR) {
2863e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException("OpenBasicChannel() failed");
287e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
288e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR,
289e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                        "OpenBasicChannel() failed");
290ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
291e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi
292ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Channel basicChannel = new Channel(session, this, 0, selectResponse,
293ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    listener);
294ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            basicChannel.setChannelAccess(channelAccess);
295ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
296ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectedAid = getSelectedAid(selectResponse);
297ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (selectedAid != null) {
298ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                basicChannel.hasSelectedAid(true, selectedAid);
299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else {
300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                basicChannel.hasSelectedAid((aid != null) ? true : false, aid);
301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
303ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (aid != null) {
304ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mDefaultApplicationSelectedOnBasicChannel = false;
305ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
306ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.put(0, basicChannel);
307ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return basicChannel;
308ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
309ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
310ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
311ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
312ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a logical Channel without Channel Access initialization.
313ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
3143e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka    public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException {
315ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0);
316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a logical Channel with AID.
320ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
3213e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka    public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2,
3223e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            ISecureElementListener listener, String packageName, int pid) throws IOException {
323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length == 0) {
324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            aid = null;
325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
326ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("AID out of range");
327ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (!mIsConnected) {
3283e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            throw new IOException("Secure Element is not connected");
329ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
330ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
331ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ChannelAccess channelAccess = null;
332ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (packageName != null) {
333ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.w(mTag, "Enable access control on logical channel for " + packageName);
334ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            channelAccess = setUpChannelAccess(aid, packageName, true, pid);
335ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
336ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
337ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
338ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
339ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
3403e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
3413e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
3423e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
3433e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        new ISecureElement.openLogicalChannelCallback() {
3443e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            @Override
3453e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            public void onValues(LogicalChannelResponse response, byte halStatus) {
3463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                status[0] = halStatus;
3473e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                responseArray[0] = response;
3483e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                return;
3493e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            }
3503e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        });
3513e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (RemoteException e) {
3523e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException(e.getMessage());
3533e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
3543e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
355ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
356ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
357ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
358ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("OpenLogicalChannel() failed");
359ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.IOERROR) {
3603e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException("OpenLogicalChannel() failed");
361ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
362ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR,
363ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        "OpenLogicalChannel() failed");
364ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
365ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) {
366ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
367ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
368ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            int channelNumber = responseArray[0].channelNumber;
369ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse);
370ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Channel logicalChannel = new Channel(session, this, channelNumber,
371ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    selectResponse, listener);
372ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            logicalChannel.setChannelAccess(channelAccess);
373ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
374ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectedAid = selectedAid = getSelectedAid(selectResponse);
375ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (selectedAid != null) {
376ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                logicalChannel.hasSelectedAid(true, selectedAid);
377ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else {
378ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                logicalChannel.hasSelectedAid((aid != null) ? true : false, aid);
379ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
380ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
381ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.put(channelNumber, logicalChannel);
382ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return logicalChannel;
383ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
384ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
385ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
386ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
387ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns true if the given AID can be selected on the Terminal
388ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
389ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean isAidSelectable(byte[] aid) {
390ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid == null) {
391ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NullPointerException("aid must not be null");
392ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (!mIsConnected) {
393ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Secure Element is not connected");
394ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return false;
395ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
396ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
397ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
398ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
399ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
400ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
401ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00,
402ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        new ISecureElement.openLogicalChannelCallback() {
403ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            @Override
404ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            public void onValues(LogicalChannelResponse response, byte halStatus) {
405ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                status[0] = halStatus;
406ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                responseArray[0] = response;
407ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                return;
408ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            }
409ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        });
410ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (status[0] == SecureElementStatus.SUCCESS) {
411ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    mSEHal.closeChannel(responseArray[0].channelNumber);
412ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    return true;
413ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
414ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return false;
415ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (RemoteException e) {
416ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Error in isAidSelectable() returning false" + e);
417ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return false;
418ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
419ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
420ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
421ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
422ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
423ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Transmits the specified command and returns the response.
424ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     *
425ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * @param cmd the command APDU to be transmitted.
426ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * @return the response received.
427ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
4283878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    public byte[] transmit(byte[] cmd) throws IOException {
429ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (!mIsConnected) {
430ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Secure Element is not connected");
4313878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException("Secure Element is not connected");
432ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
433ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
434ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] rsp = transmitInternal(cmd);
435ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int sw1 = rsp[rsp.length - 2] & 0xFF;
436ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int sw2 = rsp[rsp.length - 1] & 0xFF;
437ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
438ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (sw1 == 0x6C) {
439ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            cmd[cmd.length - 1] = rsp[rsp.length - 1];
440ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            rsp = transmitInternal(cmd);
441ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (sw1 == 0x61) {
442ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            do {
443ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] getResponseCmd = new byte[]{
444ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2
445ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                };
446ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] tmp = transmitInternal(getResponseCmd);
447ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] aux = rsp;
448ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                rsp = new byte[aux.length + tmp.length - 2];
449ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                System.arraycopy(aux, 0, rsp, 0, aux.length - 2);
450ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length);
451ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                sw1 = rsp[rsp.length - 2] & 0xFF;
452ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                sw2 = rsp[rsp.length - 1] & 0xFF;
453ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } while (sw1 == 0x61);
454ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
455ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return rsp;
456ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
457ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
4583878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    private byte[] transmitInternal(byte[] cmd) throws IOException {
4593878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        ArrayList<Byte> response;
4603878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        try {
4613878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            response = mSEHal.transmit(byteArrayToArrayList(cmd));
4623878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        } catch (RemoteException e) {
4633878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException(e.getMessage());
4643878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        }
465ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (response.isEmpty()) {
4663878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException("Error in transmit()");
467ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
468ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] rsp = arrayListToByteArray(response);
469ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mDebug) {
470ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd));
471ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp));
472ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
473ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return rsp;
474ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
475ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
476ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
477ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Checks if the application is authorized to receive the transaction event.
478ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
479ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean[] isNfcEventAllowed(
480ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            PackageManager packageManager,
481ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] aid,
482ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            String[] packageNames,
483ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            boolean checkRefreshTag) {
484ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer == null) {
485ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Access Control Enforcer not properly set up");
486ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            initializeAccessControl();
487ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
488ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mAccessControlEnforcer.setPackageManager(packageManager);
489ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
490ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
491ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
492ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames,
493ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        checkRefreshTag);
494ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (Exception e) {
495ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
496ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
497ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
498ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
499ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
500ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
501ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
502ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns true if the Secure Element is present
503ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
504ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean isSecureElementPresent() {
505ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
506ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return mSEHal.isCardPresent();
507ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
508ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Error in isSecureElementPresent() " + e);
509ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return false;
510ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
511ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
512ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
513ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
514ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Initialize the Access Control and set up the channel access.
515ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
5163e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka    private ChannelAccess setUpChannelAccess(byte[] aid, String packageName,
5173e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            boolean checkRefreshTag, int pid) throws IOException {
518ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer == null) {
519ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Access Control Enforcer not properly set up");
520ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            initializeAccessControl();
521ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
522ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());
523ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
524ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
525ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
526ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ChannelAccess channelAccess =
527ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mAccessControlEnforcer.setUpChannelAccess(aid, packageName,
528ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                checkRefreshTag);
529ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                channelAccess.setCallingPid(pid);
530ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return channelAccess;
5313e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (IOException e) {
5323e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw e;
533ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (Exception e) {
534ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new SecurityException("Exception in setUpChannelAccess()" + e);
535ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
536ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
537ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
538ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
539ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
540ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Initializes the Access Control for this Terminal
541ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
542ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private synchronized void initializeAccessControl() {
543ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
544ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mAccessControlEnforcer == null) {
545ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mAccessControlEnforcer = new AccessControlEnforcer(this);
546ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
547ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mAccessControlEnforcer.initialize(true);
548ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
549ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
550ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
551ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public AccessControlEnforcer getAccessControlEnforcer() {
552ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return mAccessControlEnforcer;
553ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
554ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
555ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private byte[] getSelectedAid(byte[] selectResponse) {
556ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectedAid = null;
557ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if ((selectResponse != null && selectResponse.length >= 2)
558ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                && (selectResponse.length == (selectResponse[1] + 4))
559ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                && // header(2) + SW(2)
560ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ((selectResponse[0] == (byte) 0x62)
561ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        || (selectResponse[0] == (byte) 0x6F))) { // FCP or FCI template
562ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            int nextTlv = 2;
563ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            while (selectResponse.length > nextTlv) {
564ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (selectResponse[nextTlv] == (byte) 0x84) {
565ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (selectResponse.length >= (nextTlv + selectResponse[nextTlv + 1] + 2)) {
566ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        selectedAid = new byte[selectResponse[nextTlv + 1]];
567ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        System.arraycopy(
568ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                selectResponse, nextTlv + 2, selectedAid, 0,
569ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                selectResponse[nextTlv + 1]);
570ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
571ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    break;
572ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } else {
573ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    nextTlv += 2 + selectResponse[nextTlv + 1];
574ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
575ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
576ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
577ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return selectedAid;
578ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
579ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
580ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /** Dump data for debug purpose . */
581ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void dump(PrintWriter writer) {
582ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName);
583ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
584ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
585ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("mIsConnected:" + mIsConnected);
586ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
587ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
588ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        /* Dump the list of currunlty openned channels */
589ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("List of open channels:");
590ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
591ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Channel channel : mChannels.values()) {
592ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("channel " + channel.getChannelNumber() + ": ");
593ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("package: " + channel.getChannelAccess().getPackageName());
594ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("pid: " + channel.getChannelAccess().getCallingPid());
595ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("aid selected: " + channel.hasSelectedAid());
596ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("basic channel: " + channel.isBasicChannel());
597ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println();
598ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
599ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
600ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
601ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        /* Dump ACE data */
602ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer != null) {
603ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mAccessControlEnforcer.dump(writer);
604ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
605ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
606ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
607ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    // Implementation of the SecureElement Reader interface according to OMAPI.
608ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    final class SecureElementReader extends ISecureElementReader.Stub {
609ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
610ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final SecureElementService mService;
611ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final ArrayList<SecureElementSession> mSessions =
612ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                new ArrayList<SecureElementSession>();
613ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
614ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        SecureElementReader(SecureElementService service) {
615ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mService = service;
616ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
617ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
618ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public byte[] getAtr() {
619ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this.getAtr();
620ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
621ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
622ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
623ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public boolean isSecureElementPresent() throws RemoteException {
624ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this.isSecureElementPresent();
625ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
626ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
627ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
628ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void closeSessions() {
629ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
630ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                while (mSessions.size() > 0) {
631ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    try {
632ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mSessions.get(0).close();
633ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    } catch (Exception ignore) {
634ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
635ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
636ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSessions.clear();
637ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
638ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
639ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
640ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void removeSession(SecureElementSession session) {
641ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (session == null) {
642ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new NullPointerException("session is null");
643ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
644ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mSessions.remove(session);
645e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            synchronized (mLock) {
646e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                if (mSessions.size() == 0) {
647e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    mDefaultApplicationSelectedOnBasicChannel = true;
648e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                }
649e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            }
650ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
651ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
652ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
653ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public ISecureElementSession openSession() throws RemoteException {
654ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (!isSecureElementPresent()) {
655ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new ServiceSpecificException(SEService.IO_ERROR,
656ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        "Secure Element is not present.");
657ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
658ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
659ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
660ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                SecureElementSession session = mService.new SecureElementSession(this);
661ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSessions.add(session);
662ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return session;
663ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
664ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
665ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
666ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Terminal getTerminal() {
667ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this;
668ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
669ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
670ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue}
671