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) 2014-2017, The Linux Foundation.
18ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
19ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/*
20ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Contributed by: Giesecke & Devrient GmbH.
21ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
22ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
23ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepackage com.android.se;
24ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
25ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.app.Service;
26ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.Context;
27ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.Intent;
28ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.pm.PackageManager;
29ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.Binder;
30ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.IBinder;
31ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException;
32ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceManager;
333e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport android.os.ServiceSpecificException;
34ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementChannel;
35ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener;
36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader;
37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementService;
38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession;
393e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport android.se.omapi.SEService;
40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log;
41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.Terminal.SecureElementReader;
43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.FileDescriptor;
453e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException;
46ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter;
47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.security.AccessControlException;
48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList;
49ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.LinkedHashMap;
50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.List;
51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException;
52ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/**
54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Underlying implementation for OMAPI SEService
55ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */
56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic final class SecureElementService extends Service {
57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public static final String UICC_TERMINAL = "SIM";
59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public static final String ESE_TERMINAL = "eSE";
60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final String mTag = "SecureElementService";
61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    // LinkedHashMap will maintain the order of insertion
62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private LinkedHashMap<String, Terminal> mTerminals = new LinkedHashMap<String, Terminal>();
63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private final ISecureElementService.Stub mSecureElementServiceBinder =
64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            new ISecureElementService.Stub() {
65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                @Override
67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                public String[] getReaders() throws RemoteException {
68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    return mTerminals.keySet().toArray(new String[mTerminals.size()]);
69ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                @Override
72ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                public ISecureElementReader getReader(String reader)
73ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        throws RemoteException {
74ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    Log.d(mTag, "getReader() " + reader);
75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    Terminal terminal = getTerminal(reader);
76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    return terminal.new SecureElementReader(SecureElementService.this);
77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                @Override
80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                public synchronized boolean[] isNFCEventAllowed(String reader, byte[] aid,
81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        String[] packageNames)
82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        throws RemoteException {
83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (aid == null || aid.length == 0) {
84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        aid = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00};
85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
86ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (aid.length < 5 || aid.length > 16) {
87ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        throw new IllegalArgumentException("AID out of range");
88ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
89ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    if (packageNames == null || packageNames.length == 0) {
90ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        throw new IllegalArgumentException("package names not specified");
91ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
92ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    Terminal terminal = getTerminal(reader);
93a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka                    return terminal.isNfcEventAllowed(getPackageManager(), aid, packageNames);
94ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
95ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
96ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                @Override
97ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
98ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    for (Terminal terminal : mTerminals.values()) {
99ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        terminal.dump(writer);
100ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
101ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
102ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            };
103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public SecureElementService() {
105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        super();
106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
108ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /** Returns the terminal from the Reader name. */
109ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private Terminal getTerminal(String reader) {
110ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (reader == null) {
111ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new NullPointerException("reader must not be null");
112ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
113ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (reader.equals("SIM")) {
114ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            reader = "SIM1";
115ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
116ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Terminal terminal = mTerminals.get(reader);
117ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (terminal == null) {
118ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            throw new IllegalArgumentException("Reader: " + reader + " doesn't exist");
119ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
120ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return terminal;
121ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
122ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
123ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    @Override
124ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public IBinder onBind(Intent intent) {
125ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Log.i(mTag, Thread.currentThread().getName() + " onBind");
126ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (ISecureElementService.class.getName().equals(intent.getAction())) {
127ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return mSecureElementServiceBinder;
128ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
129ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        return null;
130ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
131ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
132ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    @Override
133ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void onCreate() {
134ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Log.i(mTag, Thread.currentThread().getName() + " onCreate");
135ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        createTerminals();
136ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        ServiceManager.addService(Context.SECURE_ELEMENT_SERVICE, mSecureElementServiceBinder);
137ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
138ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
139ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    /**
140ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * In case the onDestroy is called, we free the memory and
141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     * close all the channels.
142ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue     */
143ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    public void onDestroy() {
144ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        Log.i(mTag, "onDestroy");
145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        for (Terminal terminal : mTerminals.values()) {
146ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            terminal.closeChannels();
147cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka            terminal.close();
148ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
149ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
150ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
151ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private void addTerminals(String terminalName) {
152ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        int index = 1;
153cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka        String name = null;
154ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        try {
155cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka            do {
156ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                name = terminalName + Integer.toString(index);
157cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka                Terminal terminal = new Terminal(name, this);
158cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka                terminal.initialize();
159cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka                mTerminals.put(name, terminal);
160cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka            } while (++index > 0);
161ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        } catch (NoSuchElementException e) {
162cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka            Log.i(mTag, "No HAL implementation for " + name);
163cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka        } catch (RemoteException | RuntimeException e) {
164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.e(mTag, "Error in getService() for " + name);
165ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private void createTerminals() {
169cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka        // Check for all SE HAL implementations
170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        addTerminals(ESE_TERMINAL);
171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        addTerminals(UICC_TERMINAL);
172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    private String getPackageNameFromCallingUid(int uid) {
175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        PackageManager packageManager = getPackageManager();
176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        if (packageManager != null) {
177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            String[] packageName = packageManager.getPackagesForUid(uid);
178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (packageName != null && packageName.length > 0) {
179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return packageName[0];
180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        throw new AccessControlException("PackageName can not be determined");
183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    final class SecureElementSession extends ISecureElementSession.Stub {
186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final SecureElementReader mReader;
188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        /** List of open channels in use of by this client. */
189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final List<Channel> mChannels = new ArrayList<>();
190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private final Object mLock = new Object();
191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private boolean mIsClosed;
192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        private byte[] mAtr;
193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        SecureElementSession(SecureElementReader reader) {
195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (reader == null) {
196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new NullPointerException("SecureElementReader cannot be null");
197ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mReader = reader;
199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mAtr = mReader.getAtr();
200ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mIsClosed = false;
201ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
202ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
203ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public ISecureElementReader getReader() throws RemoteException {
204ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return mReader;
205ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
207ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public byte[] getAtr() throws RemoteException {
209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return mAtr;
210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
211ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void close() throws RemoteException {
214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            closeChannels();
215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mReader.removeSession(this);
216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                mIsClosed = true;
218ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
221ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        void removeChannel(Channel channel) {
222ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                if (mChannels != null) {
224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    mChannels.remove(channel);
225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
227ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
229ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
230ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public void closeChannels() throws RemoteException {
231ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
232ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                while (mChannels.size() > 0) {
233ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    try {
234ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        mChannels.get(0).close();
235ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    } catch (Exception ignore) {
236ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        Log.e(mTag, "SecureElementSession Channel - close Exception "
237ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                                + ignore.getMessage());
238ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    }
239ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                }
240ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
241ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
242ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
243ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
244ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public boolean isClosed() throws RemoteException {
245ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            synchronized (mLock) {
246ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return mIsClosed;
247ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public ISecureElementChannel openBasicChannel(byte[] aid, byte p2,
252ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ISecureElementListener listener) throws RemoteException {
253ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (isClosed()) {
254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new IllegalStateException("Session is closed");
255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (listener == null) {
256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new NullPointerException("listener must not be null");
257176b23b2a724fb8157e196ab4ff17a7fe71ab55bYoshiaki Naka            } else if (mReader.getTerminal().getName().startsWith(
258176b23b2a724fb8157e196ab4ff17a7fe71ab55bYoshiaki Naka                    SecureElementService.UICC_TERMINAL)) {
259176b23b2a724fb8157e196ab4ff17a7fe71ab55bYoshiaki Naka                return null;
260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08)
261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    && (p2 != (byte) 0x0C)) {
262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("p2 not supported: "
263ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        + String.format("%02x ", p2 & 0xFF));
264ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
265ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
266ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            String packageName = getPackageNameFromCallingUid(Binder.getCallingUid());
2673e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            Channel channel = null;
2683e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
2693e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
2703e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                channel = mReader.getTerminal().openBasicChannel(this, aid, p2, listener,
2713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        packageName, Binder.getCallingPid());
2723e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (IOException e) {
2733e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
2745091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            } catch (NoSuchElementException e) {
2755091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka                throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage());
2763e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
2773e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
278ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (channel == null) {
279ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "OpenBasicChannel() - returning null");
280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
282ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "Open basic channel success. Channel: "
283ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    + channel.getChannelNumber());
284ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
285ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.add(channel);
286ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return channel.new SecureElementChannel();
287ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
288ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
289ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        @Override
290ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        public ISecureElementChannel openLogicalChannel(byte[] aid, byte p2,
291ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                ISecureElementListener listener) throws RemoteException {
292ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (isClosed()) {
293ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new IllegalStateException("Session is closed");
294ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if (listener == null) {
295ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new NullPointerException("listener must not be null");
2961fbd76148b61a489d99a3838c765839c69243543Yoshiaki Naka            } else if (((aid == null) || (aid.length == 0)) && mReader.getTerminal().getName()
2971fbd76148b61a489d99a3838c765839c69243543Yoshiaki Naka                    .startsWith(SecureElementService.UICC_TERMINAL)) {
2981fbd76148b61a489d99a3838c765839c69243543Yoshiaki Naka                return null;
299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08)
300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    && (p2 != (byte) 0x0C)) {
301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                throw new UnsupportedOperationException("p2 not supported: "
302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                        + String.format("%02x ", p2 & 0xFF));
303ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
304ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
305ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            String packageName = getPackageNameFromCallingUid(Binder.getCallingUid());
3063e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            Channel channel = null;
3073e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka
3083e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            try {
3093e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                channel = mReader.getTerminal().openLogicalChannel(this, aid, p2, listener,
3103e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                        packageName, Binder.getCallingPid());
3113e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            } catch (IOException e) {
3123e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka                throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
3135091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka            } catch (NoSuchElementException e) {
3145091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka                throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage());
3153e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka            }
316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            if (channel == null) {
318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                Log.i(mTag, "openLogicalChannel() - returning null");
319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                return null;
320ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            }
321ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            Log.i(mTag, "openLogicalChannel() Success. Channel: "
322ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue                    + channel.getChannelNumber());
323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue
324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            mChannels.add(channel);
325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue            return channel.new SecureElementChannel();
326ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue        }
327ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue    }
328ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue}
329