Terminal.java revision a726b469d3c61c4dab20aefa75408d363431bf6a
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;
3257ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Nakaimport android.os.Build;
33ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException;
34ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceSpecificException;
35ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener;
36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader;
37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession;
38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.SEService;
39ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log;
40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.SecureElementService.SecureElementSession;
42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.internal.ByteArrayConverter;
43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.AccessControlEnforcer;
44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.ChannelAccess;
45ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException;
47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter;
48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList;
49ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Collection;
50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.HashMap;
51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Map;
52b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Nakaimport java.util.MissingResourceException;
53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException;
54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
55ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/**
56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Each Terminal represents a Secure Element.
57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Communicates to the SE via SecureElement HAL.
58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic class Terminal {
60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final String mTag;
62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final Object mLock = new Object();
64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final String mName;
65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean mIsConnected = false;
66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private Context mContext;
67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private boolean mDefaultApplicationSelectedOnBasicChannel = true;
68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
6957ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ISecureElement mSEHal;
72ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
73ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /** For each Terminal there will be one AccessController object. */
74ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private AccessControlEnforcer mAccessControlEnforcer;
75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() {
77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void onStateChange(boolean state) {
79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "OnStateChange:" + state);
81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mIsConnected = state;
82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (!state) {
83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (mAccessControlEnforcer != null) {
84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mAccessControlEnforcer.reset();
85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
86ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } else {
87a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                    try {
88a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                        initializeAccessControl();
89a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                    } catch (Exception e) {
90a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                        // ignore
91a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                    }
92e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    synchronized (mLock) {
93e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                        mDefaultApplicationSelectedOnBasicChannel = true;
94e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    }
95ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
96ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
97ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
98ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    };
99ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
100ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public Terminal(String name, Context context, ISecureElement seHal) {
101ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (seHal == null) {
102ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("ISecureElement cannot be null ");
103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mContext = context;
105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mName = name;
106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mTag = "SecureElement-Terminal-" + getName();
107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mSEHal = seHal;
108ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
109ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            seHal.init(mHalCallback);
110ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
111ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
112ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
113ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
114ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private ArrayList<Byte> byteArrayToArrayList(byte[] array) {
115ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ArrayList<Byte> list = new ArrayList<Byte>();
116ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (array == null) {
117ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return list;
118ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
119ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
120ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Byte b : array) {
121ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            list.add(b);
122ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
123ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return list;
124ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
125ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
126ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private byte[] arrayListToByteArray(ArrayList<Byte> list) {
127ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Byte[] byteArray = list.toArray(new Byte[list.size()]);
128ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int i = 0;
129ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] result = new byte[list.size()];
130ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Byte b : byteArray) {
131ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            result[i++] = b.byteValue();
132ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
133ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return result;
134ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
135ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
136ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
137ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Closes the given channel
138ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
139ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void closeChannel(Channel channel) {
140ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (channel == null) {
141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return;
142ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
143fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi        if (mIsConnected) {
144ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte status = mSEHal.closeChannel((byte) channel.getChannelNumber());
146fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                /* For Basic Channels, errors are expected.
147fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                 * Underlying implementations use this call as an indication when there
148fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                 * aren't any users actively using the channel, and the chip can go
149fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                 * into low power state.
150fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                 */
151fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi                if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) {
152ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    Log.e(mTag, "Error closing channel " + channel.getChannelNumber());
153ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
154ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (RemoteException e) {
155ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Exception in closeChannel() " + e);
156ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
157ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
158ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
159ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.remove(channel.getChannelNumber(), channel);
160ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mChannels.get(channel.getChannelNumber()) != null) {
161ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Removing channel failed");
162ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
163ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
165ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * This method is called in SecureElementService:onDestroy to clean up
168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * all open channels.
169ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public synchronized void closeChannels() {
171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Collection<Channel> col = mChannels.values();
172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Channel[] channelList = col.toArray(new Channel[col.size()]);
173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Channel channel : channelList) {
174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            closeChannel(channel);
175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public String getName() {
179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return mName;
180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns the ATR of the Secure Element, or null if not available.
184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public byte[] getAtr() {
186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (!mIsConnected) {
187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return null;
188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            ArrayList<Byte> responseList = mSEHal.getAtr();
192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (responseList.isEmpty()) {
193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return arrayListToByteArray(responseList);
196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
197ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Exception in getAtr()" + e);
198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return null;
199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
200ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
201ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
202ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
203ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Selects the default application on the basic channel.
204ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     *
205ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * If there is an exception selecting the default application, select
206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * is performed with the default access control aid.
207ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void selectDefaultApplication() {
209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            select(null);
211ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (NoSuchElementException e) {
212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (getAccessControlEnforcer() != null) {
213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                try {
214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    select(mAccessControlEnforcer.getDefaultAccessControlAid());
215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } catch (Exception ignore) {
216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
2183878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        } catch (Exception ignore) {
219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
221ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
2223878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    private void select(byte[] aid) throws IOException {
223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int commandSize = (aid == null ? 0 : aid.length) + 5;
224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectCommand = new byte[commandSize];
225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[0] = 0x00;
226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[1] = (byte) 0xA4;
227ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[2] = 0x04;
228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        selectCommand[3] = 0x00;
229ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length != 0) {
230ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectCommand[4] = (byte) aid.length;
231ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            System.arraycopy(aid, 0, selectCommand, 5, aid.length);
232ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else {
233ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectCommand[4] = 0x00;
234ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
235ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectResponse = transmit(selectCommand);
236ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (selectResponse.length < 2) {
237ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectResponse = null;
238ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NoSuchElementException("Response length is too small");
239ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
240e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi        int sw1 = selectResponse[selectResponse.length - 2] & 0xFF;
241e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi        int sw2 = selectResponse[selectResponse.length - 1] & 0xFF;
242ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (sw1 != 0x90 || sw2 != 0x00) {
243ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            selectResponse = null;
244ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NoSuchElementException("Status word is incorrect");
245ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
246ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
247ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a Basic Channel with the given AID and P2 paramters
250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2,
2525091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            ISecureElementListener listener, String packageName, int pid) throws IOException,
2535091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            NoSuchElementException {
254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length == 0) {
255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            aid = null;
256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
257ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("AID out of range");
2583e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka        } else if (!mIsConnected) {
2593e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            throw new IOException("Secure Element is not connected");
260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Log.w(mTag, "Enable access control on basic channel for " + packageName);
263b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka        ChannelAccess channelAccess;
264b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka        try {
265a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            channelAccess = setUpChannelAccess(aid, packageName, pid);
266b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka        } catch (MissingResourceException e) {
267b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka            return null;
268b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka        }
269ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
270ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
271ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mChannels.get(0) != null) {
272ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "basic channel in use");
273ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
274ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
275ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) {
276ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "default application is not selected");
277ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
278ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
279ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            ArrayList<byte[]> responseList = new ArrayList<byte[]>();
281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
2823e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
2833e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
2843e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
2853e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        new ISecureElement.openBasicChannelCallback() {
2863e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            @Override
2873e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
2883e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                status[0] = halStatus;
2893e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                responseList.add(arrayListToByteArray(responseObject));
2903e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                return;
2913e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            }
2923e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        });
2933e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (RemoteException e) {
2943e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException(e.getMessage());
2953e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
2963e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
297ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectResponse = responseList.get(0);
298ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("OpenBasicChannel() failed");
302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.IOERROR) {
3033e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException("OpenBasicChannel() failed");
304e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
3055091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka                throw new NoSuchElementException("OpenBasicChannel() failed");
306ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
307e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi
308ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Channel basicChannel = new Channel(session, this, 0, selectResponse,
309ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    listener);
310ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            basicChannel.setChannelAccess(channelAccess);
311ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
312ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectedAid = getSelectedAid(selectResponse);
313ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (selectedAid != null) {
314ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                basicChannel.hasSelectedAid(true, selectedAid);
315ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else {
316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                basicChannel.hasSelectedAid((aid != null) ? true : false, aid);
317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (aid != null) {
320ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mDefaultApplicationSelectedOnBasicChannel = false;
321ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
322ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.put(0, basicChannel);
323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return basicChannel;
324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
326ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
327ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
328ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a logical Channel without Channel Access initialization.
329ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
3305091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka    public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException,
3315091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            NoSuchElementException {
332ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0);
333ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
334ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
335ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
336ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Opens a logical Channel with AID.
337ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
3383e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka    public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2,
3395091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            ISecureElementListener listener, String packageName, int pid) throws IOException,
3405091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            NoSuchElementException {
341ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid != null && aid.length == 0) {
342ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            aid = null;
343ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
344ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("AID out of range");
345ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (!mIsConnected) {
3463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            throw new IOException("Secure Element is not connected");
347ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
348ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
349ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ChannelAccess channelAccess = null;
350ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (packageName != null) {
351ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.w(mTag, "Enable access control on logical channel for " + packageName);
352b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka            try {
353a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                channelAccess = setUpChannelAccess(aid, packageName, pid);
354b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka            } catch (MissingResourceException e) {
355b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka                return null;
356b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka            }
357ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
358ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
359ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
360ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
361ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
3623e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
3633e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
3643e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
3653e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        new ISecureElement.openLogicalChannelCallback() {
3663e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            @Override
3673e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            public void onValues(LogicalChannelResponse response, byte halStatus) {
3683e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                status[0] = halStatus;
3693e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                responseArray[0] = response;
3703e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                                return;
3713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                            }
3723e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        });
3733e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (RemoteException e) {
3743e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException(e.getMessage());
3753e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
3763e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
377ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
378ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
379ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
380ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("OpenLogicalChannel() failed");
381ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.IOERROR) {
3823e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new IOException("OpenLogicalChannel() failed");
383ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
3845091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka                throw new NoSuchElementException("OpenLogicalChannel() failed");
385ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
386ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) {
387ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
388ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
389ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            int channelNumber = responseArray[0].channelNumber;
390ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse);
391ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Channel logicalChannel = new Channel(session, this, channelNumber,
392ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    selectResponse, listener);
393ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            logicalChannel.setChannelAccess(channelAccess);
394ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
395ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] selectedAid = selectedAid = getSelectedAid(selectResponse);
396ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (selectedAid != null) {
397ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                logicalChannel.hasSelectedAid(true, selectedAid);
398ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else {
399ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                logicalChannel.hasSelectedAid((aid != null) ? true : false, aid);
400ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
401ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
402ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.put(channelNumber, logicalChannel);
403ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return logicalChannel;
404ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
405ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
406ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
407ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
408ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns true if the given AID can be selected on the Terminal
409ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
410ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean isAidSelectable(byte[] aid) {
411ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (aid == null) {
412ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NullPointerException("aid must not be null");
413ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (!mIsConnected) {
414ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Secure Element is not connected");
415ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return false;
416ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
417ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
418ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
419ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
420ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            byte[] status = new byte[1];
421ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
422ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00,
423ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        new ISecureElement.openLogicalChannelCallback() {
424ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            @Override
425ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            public void onValues(LogicalChannelResponse response, byte halStatus) {
426ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                status[0] = halStatus;
427ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                responseArray[0] = response;
428ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                return;
429ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                            }
430ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        });
431ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (status[0] == SecureElementStatus.SUCCESS) {
432ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    mSEHal.closeChannel(responseArray[0].channelNumber);
433ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    return true;
434ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
435ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return false;
436ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (RemoteException e) {
437ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.e(mTag, "Error in isAidSelectable() returning false" + e);
438ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return false;
439ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
440ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
441ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
442ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
443ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
444ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Transmits the specified command and returns the response.
445ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     *
446ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * @param cmd the command APDU to be transmitted.
447ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * @return the response received.
448ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
4493878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    public byte[] transmit(byte[] cmd) throws IOException {
450ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (!mIsConnected) {
451ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Secure Element is not connected");
4523878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException("Secure Element is not connected");
453ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
454ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
455ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] rsp = transmitInternal(cmd);
456ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int sw1 = rsp[rsp.length - 2] & 0xFF;
457ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int sw2 = rsp[rsp.length - 1] & 0xFF;
458ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
459ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (sw1 == 0x6C) {
460ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            cmd[cmd.length - 1] = rsp[rsp.length - 1];
461ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            rsp = transmitInternal(cmd);
462ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } else if (sw1 == 0x61) {
463ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            do {
464ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] getResponseCmd = new byte[]{
465ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2
466ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                };
467ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] tmp = transmitInternal(getResponseCmd);
468ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                byte[] aux = rsp;
469ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                rsp = new byte[aux.length + tmp.length - 2];
470ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                System.arraycopy(aux, 0, rsp, 0, aux.length - 2);
471ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length);
472ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                sw1 = rsp[rsp.length - 2] & 0xFF;
473ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                sw2 = rsp[rsp.length - 1] & 0xFF;
474ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } while (sw1 == 0x61);
475ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
476ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return rsp;
477ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
478ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
4793878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka    private byte[] transmitInternal(byte[] cmd) throws IOException {
4803878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        ArrayList<Byte> response;
4813878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        try {
4823878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            response = mSEHal.transmit(byteArrayToArrayList(cmd));
4833878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        } catch (RemoteException e) {
4843878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException(e.getMessage());
4853878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka        }
486ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (response.isEmpty()) {
4873878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka            throw new IOException("Error in transmit()");
488ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
489ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] rsp = arrayListToByteArray(response);
49057ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka        if (DEBUG) {
491ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd));
492ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp));
493ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
494ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return rsp;
495ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
496ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
497ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
498ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Checks if the application is authorized to receive the transaction event.
499ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
500a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka    public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid,
501a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            String[] packageNames) {
502a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka        boolean checkRefreshTag = true;
503ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer == null) {
504a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            try {
505a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                initializeAccessControl();
506a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // Just finished to initialize the access control enforcer.
507a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // It is too much to check the refresh tag in this case.
508a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                checkRefreshTag = false;
509a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            } catch (Exception e) {
510a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
511a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                return null;
512a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            }
513ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
514ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mAccessControlEnforcer.setPackageManager(packageManager);
515ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
516ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
517ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
518ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames,
519ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        checkRefreshTag);
520ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (Exception e) {
521ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
522ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
523ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
524ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
525ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
526ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
527ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
528ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Returns true if the Secure Element is present
529ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
530ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public boolean isSecureElementPresent() {
531ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
532ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return mSEHal.isCardPresent();
533ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (RemoteException e) {
534ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Error in isSecureElementPresent() " + e);
535ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return false;
536ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
537ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
538ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
539ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
540ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Initialize the Access Control and set up the channel access.
541ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
542a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka    private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid)
543a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            throws IOException, MissingResourceException {
544a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka        boolean checkRefreshTag = true;
545ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer == null) {
546ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            initializeAccessControl();
547a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            // Just finished to initialize the access control enforcer.
548a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            // It is too much to check the refresh tag in this case.
549a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            checkRefreshTag = false;
550ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
551ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());
552ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
553ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
554ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            try {
555ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ChannelAccess channelAccess =
556ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mAccessControlEnforcer.setUpChannelAccess(aid, packageName,
557ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                checkRefreshTag);
558ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                channelAccess.setCallingPid(pid);
559ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return channelAccess;
560a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            } catch (IOException | MissingResourceException e) {
561b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka                throw e;
562ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } catch (Exception e) {
563ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new SecurityException("Exception in setUpChannelAccess()" + e);
564ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
565ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
566ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
567ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
568ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
569ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * Initializes the Access Control for this Terminal
570ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
571a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka    private synchronized void initializeAccessControl() throws IOException,
572a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            MissingResourceException {
573ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        synchronized (mLock) {
574ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (mAccessControlEnforcer == null) {
575ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mAccessControlEnforcer = new AccessControlEnforcer(this);
576ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
577a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            try {
578a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                mAccessControlEnforcer.initialize();
579a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            } catch (IOException | MissingResourceException e) {
580a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // Retrieving access rules failed because of an IO error happened between
581a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // the terminal and the secure element or the lack of a logical channel available.
582a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // It might be a temporary failure, so the terminal shall attempt to cache
583a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                // the access rules again later.
584a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                mAccessControlEnforcer = null;
585a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                throw e;
586a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka            }
587ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
588ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
589ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
590ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public AccessControlEnforcer getAccessControlEnforcer() {
591ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return mAccessControlEnforcer;
592ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
593ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
594ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private byte[] getSelectedAid(byte[] selectResponse) {
595ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        byte[] selectedAid = null;
596ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if ((selectResponse != null && selectResponse.length >= 2)
597ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                && (selectResponse.length == (selectResponse[1] + 4))
598ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                && // header(2) + SW(2)
599ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ((selectResponse[0] == (byte) 0x62)
600ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        || (selectResponse[0] == (byte) 0x6F))) { // FCP or FCI template
601ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            int nextTlv = 2;
602ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            while (selectResponse.length > nextTlv) {
603ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (selectResponse[nextTlv] == (byte) 0x84) {
604ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (selectResponse.length >= (nextTlv + selectResponse[nextTlv + 1] + 2)) {
605ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        selectedAid = new byte[selectResponse[nextTlv + 1]];
606ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        System.arraycopy(
607ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                selectResponse, nextTlv + 2, selectedAid, 0,
608ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                selectResponse[nextTlv + 1]);
609ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
610ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    break;
611ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                } else {
612ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    nextTlv += 2 + selectResponse[nextTlv + 1];
613ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
614ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
615ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
616ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return selectedAid;
617ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
618ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
619ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /** Dump data for debug purpose . */
620ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void dump(PrintWriter writer) {
621ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName);
622ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
623ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
624ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("mIsConnected:" + mIsConnected);
625ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
626ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
627ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        /* Dump the list of currunlty openned channels */
628ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println("List of open channels:");
629ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
630ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Channel channel : mChannels.values()) {
631ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("channel " + channel.getChannelNumber() + ": ");
632ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("package: " + channel.getChannelAccess().getPackageName());
633ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("pid: " + channel.getChannelAccess().getCallingPid());
634ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("aid selected: " + channel.hasSelectedAid());
635ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println("basic channel: " + channel.isBasicChannel());
636ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            writer.println();
637ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
638ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        writer.println();
639ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
640ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        /* Dump ACE data */
641ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (mAccessControlEnforcer != null) {
642ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mAccessControlEnforcer.dump(writer);
643ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
644ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
645ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
646ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    // Implementation of the SecureElement Reader interface according to OMAPI.
647ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    final class SecureElementReader extends ISecureElementReader.Stub {
648ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
649ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final SecureElementService mService;
650ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final ArrayList<SecureElementSession> mSessions =
651ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                new ArrayList<SecureElementSession>();
652ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
653ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        SecureElementReader(SecureElementService service) {
654ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mService = service;
655ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
656ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
657ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public byte[] getAtr() {
658ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this.getAtr();
659ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
660ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
661ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
662ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public boolean isSecureElementPresent() throws RemoteException {
663ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this.isSecureElementPresent();
664ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
665ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
666ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
667ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void closeSessions() {
668ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
669ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                while (mSessions.size() > 0) {
670ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    try {
671ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mSessions.get(0).close();
672ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    } catch (Exception ignore) {
673ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
674ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
675ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSessions.clear();
676ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
677ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
678ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
679ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void removeSession(SecureElementSession session) {
680ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (session == null) {
681ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new NullPointerException("session is null");
682ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
683ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mSessions.remove(session);
684e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            synchronized (mLock) {
685e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                if (mSessions.size() == 0) {
686e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                    mDefaultApplicationSelectedOnBasicChannel = true;
687e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi                }
688e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi            }
689ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
690ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
691ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
692ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public ISecureElementSession openSession() throws RemoteException {
693ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (!isSecureElementPresent()) {
694ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new ServiceSpecificException(SEService.IO_ERROR,
695ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        "Secure Element is not present.");
696ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
697ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
698ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
699ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                SecureElementSession session = mService.new SecureElementSession(this);
700ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mSessions.add(session);
701ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return session;
702ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
703ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
704ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
705ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Terminal getTerminal() {
706ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return Terminal.this;
707ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
708ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
709ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue}
710