From c230125cd27b1e0848e91ae510cf38f828ac6985 Mon Sep 17 00:00:00 2001 From: Ruchi Kandoi Date: Tue, 27 Mar 2018 10:03:34 -0700 Subject: [PATCH] Make OMAPI stricter - Channel implements java.nio.Channels.Channel. - openBasicChannel(aid) and openLogicalChannel(aid) is added back. - Add finalizers for the classes. - SecureElementListener -> onConnectedListener Bug: 76448978 Test: CtsOmapiTestCases Change-Id: I7f92c4dcb5c08a72d32ac9440872ab853badec1d (cherry picked from commit f0082409b56ea9c5e2b0839c87ee37db26789b59) --- api/current.txt | 16 +++++---- core/java/android/se/omapi/Channel.java | 18 +++++----- core/java/android/se/omapi/Reader.java | 2 +- core/java/android/se/omapi/SEService.java | 19 ++++++----- core/java/android/se/omapi/Session.java | 56 ++++++++++++++++++++++++++++++- 5 files changed, 84 insertions(+), 27 deletions(-) diff --git a/api/current.txt b/api/current.txt index 3b182171cf29..9ab31f5fc8ef 100644 --- a/api/current.txt +++ b/api/current.txt @@ -38380,17 +38380,17 @@ package android.sax { package android.se.omapi { - public class Channel { + public final class Channel implements java.nio.channels.Channel { method public void close(); method public byte[] getSelectResponse(); method public android.se.omapi.Session getSession(); method public boolean isBasicChannel(); - method public boolean isClosed(); + method public boolean isOpen(); method public boolean selectNext() throws java.io.IOException; method public byte[] transmit(byte[]) throws java.io.IOException; } - public class Reader { + public final class Reader { method public void closeSessions(); method public java.lang.String getName(); method public android.se.omapi.SEService getSEService(); @@ -38398,26 +38398,28 @@ package android.se.omapi { method public android.se.omapi.Session openSession() throws java.io.IOException; } - public class SEService { - ctor public SEService(android.content.Context, android.se.omapi.SEService.SecureElementListener); + public final class SEService { + ctor public SEService(android.content.Context, android.se.omapi.SEService.OnConnectedListener); method public android.se.omapi.Reader[] getReaders(); method public java.lang.String getVersion(); method public boolean isConnected(); method public void shutdown(); } - public static abstract interface SEService.SecureElementListener { + public static abstract interface SEService.OnConnectedListener { method public abstract void onServiceConnected(); } - public class Session { + public final class Session { method public void close(); method public void closeChannels(); method public byte[] getATR(); method public android.se.omapi.Reader getReader(); method public boolean isClosed(); method public android.se.omapi.Channel openBasicChannel(byte[], byte) throws java.io.IOException; + method public android.se.omapi.Channel openBasicChannel(byte[]) throws java.io.IOException; method public android.se.omapi.Channel openLogicalChannel(byte[], byte) throws java.io.IOException; + method public android.se.omapi.Channel openLogicalChannel(byte[]) throws java.io.IOException; } } diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java index c8efede3419e..5db3c1a9a707 100644 --- a/core/java/android/se/omapi/Channel.java +++ b/core/java/android/se/omapi/Channel.java @@ -39,7 +39,7 @@ import java.io.IOException; * * @see GlobalPlatform Open Mobile API */ -public class Channel { +public final class Channel implements java.nio.channels.Channel { private static final String TAG = "OMAPI.Channel"; private Session mSession; @@ -64,7 +64,7 @@ public class Channel { * before closing the channel. */ public void close() { - if (!isClosed()) { + if (isOpen()) { synchronized (mLock) { try { mChannel.close(); @@ -76,21 +76,21 @@ public class Channel { } /** - * Tells if this channel is closed. + * Tells if this channel is open. * - * @return true if the channel is closed or in case of an error. - * false otherwise. + * @return false if the channel is closed or in case of an error. + * true otherwise. */ - public boolean isClosed() { + public boolean isOpen() { if (!mService.isConnected()) { Log.e(TAG, "service not connected to system"); - return true; + return false; } try { - return mChannel.isClosed(); + return !mChannel.isClosed(); } catch (RemoteException e) { Log.e(TAG, "Exception in isClosed()"); - return true; + return false; } } diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java index 9be3da6c6327..80262f7533c8 100644 --- a/core/java/android/se/omapi/Reader.java +++ b/core/java/android/se/omapi/Reader.java @@ -37,7 +37,7 @@ import java.io.IOException; * * @see GlobalPlatform Open Mobile API */ -public class Reader { +public final class Reader { private static final String TAG = "OMAPI.Reader"; private final String mName; diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java index 311dc4c7ae10..1f69df898d03 100644 --- a/core/java/android/se/omapi/SEService.java +++ b/core/java/android/se/omapi/SEService.java @@ -40,7 +40,7 @@ import java.util.HashMap; * * @see SIMalliance Open Mobile API v3.0 */ -public class SEService { +public final class SEService { /** * Error code used with ServiceSpecificException. @@ -62,7 +62,7 @@ public class SEService { /** * Interface to send call-backs to the application when the service is connected. */ - public interface SecureElementListener { + public interface OnConnectedListener { /** * Called by the framework when the service is connected. */ @@ -74,7 +74,7 @@ public class SEService { * SEService could be bound to the backend. */ private class SEListener extends ISecureElementListener.Stub { - public SecureElementListener mListener = null; + public OnConnectedListener mListener = null; @Override public IBinder asBinder() { @@ -122,9 +122,9 @@ public class SEService { * the context of the calling application. Cannot be * null. * @param listener - * a SecureElementListener object. + * a OnConnectedListener object. */ - public SEService(@NonNull Context context, @NonNull SecureElementListener listener) { + public SEService(@NonNull Context context, @NonNull OnConnectedListener listener) { if (context == null) { throw new NullPointerException("context must not be null"); @@ -171,12 +171,12 @@ public class SEService { } /** - * Returns the list of available Secure Element readers. + * Returns an array of available Secure Element readers. * There must be no duplicated objects in the returned list. * All available readers shall be listed even if no card is inserted. * - * @return The readers list, as an array of Readers. If there are no - * readers the returned array is of length 0. + * @return An array of Readers. If there are no readers the returned array + * is of length 0. */ public @NonNull Reader[] getReaders() { if (mSecureElementService == null) { @@ -212,7 +212,8 @@ public class SEService { * (including any binding to an underlying service). * As a result isConnected() will return false after shutdown() was called. * After this method call, the SEService object is not connected. - * It is recommended to call this method in the termination method of the calling application + * This method should be called when connection to the Secure Element is not needed + * or in the termination method of the calling application * (or part of this application) which is bound to this SEService. */ public void shutdown() { diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java index adfeddd504c4..d5f8c82bf47e 100644 --- a/core/java/android/se/omapi/Session.java +++ b/core/java/android/se/omapi/Session.java @@ -39,7 +39,7 @@ import java.util.NoSuchElementException; * * @see SIMalliance Open Mobile API v3.0 */ -public class Session { +public final class Session { private final Object mLock = new Object(); private final SEService mService; @@ -225,6 +225,32 @@ public class Session { } /** + * This method is provided to ease the development of mobile application and for compliancy + * with existing applications. + * This method is equivalent to openBasicChannel(aid, P2=0x00) + * + * @param aid the AID of the Applet to be selected on this channel, as a + * byte array, or null if no Applet is to be selected. + * @throws IOException if there is a communication problem to the reader or + * the Secure Element. + * @throws IllegalStateException if the Secure Element session is used after + * being closed. + * @throws IllegalArgumentException if the aid's length is not within 5 to + * 16 (inclusive). + * @throws SecurityException if the calling application cannot be granted + * access to this AID or the default Applet on this + * session. + * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be + * selected. + * @throws UnsupportedOperationException if the given P2 parameter is not + * supported by the device + * @return an instance of Channel if available or null. + */ + public @Nullable Channel openBasicChannel(@Nullable byte[] aid) throws IOException { + return openBasicChannel(aid, (byte) 0x00); + } + + /** * Open a logical channel with the Secure Element, selecting the Applet represented by * the given AID. If the AID is null, which means no Applet is to be selected on this * channel, the default Applet is used. It's up to the Secure Element to choose which @@ -304,4 +330,32 @@ public class Session { } } } + + /** + * This method is provided to ease the development of mobile application and for compliancy + * with existing applications. + * This method is equivalent to openLogicalChannel(aid, P2=0x00) + * + * @param aid the AID of the Applet to be selected on this channel, as a + * byte array. + * @throws IOException if there is a communication problem to the reader or + * the Secure Element. + * @throws IllegalStateException if the Secure Element is used after being + * closed. + * @throws IllegalArgumentException if the aid's length is not within 5 to + * 16 (inclusive). + * @throws SecurityException if the calling application cannot be granted + * access to this AID or the default Applet on this + * session. + * @throws NoSuchElementException if the AID on the Secure Element is not + * available or cannot be selected or a logical channel is already + * open to a non-multiselectable Applet. + * @throws UnsupportedOperationException if the given P2 parameter is not + * supported by the device. + * @return an instance of Channel. Null if the Secure Element is unable to + * provide a new logical channel. + */ + public @Nullable Channel openLogicalChannel(@Nullable byte[] aid) throws IOException { + return openLogicalChannel(aid, (byte) 0x00); + } } -- 2.11.0