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