Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1fc0255 authored by Ruchi Kandoi's avatar Ruchi Kandoi Committed by Android (Google) Code Review
Browse files

Merge changes from topic "omapi" into pi-dev

* changes:
  Add an Executor for the onConnectedListener
  Make OMAPI stricter
parents 47721fa5 6a580939
Loading
Loading
Loading
Loading
+10 −8
Original line number Original line Diff line number Diff line
@@ -38395,17 +38395,17 @@ package android.sax {
package android.se.omapi {
package android.se.omapi {
  public class Channel {
  public final class Channel implements java.nio.channels.Channel {
    method public void close();
    method public void close();
    method public byte[] getSelectResponse();
    method public byte[] getSelectResponse();
    method public android.se.omapi.Session getSession();
    method public android.se.omapi.Session getSession();
    method public boolean isBasicChannel();
    method public boolean isBasicChannel();
    method public boolean isClosed();
    method public boolean isOpen();
    method public boolean selectNext() throws java.io.IOException;
    method public boolean selectNext() throws java.io.IOException;
    method public byte[] transmit(byte[]) 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 void closeSessions();
    method public java.lang.String getName();
    method public java.lang.String getName();
    method public android.se.omapi.SEService getSEService();
    method public android.se.omapi.SEService getSEService();
@@ -38413,26 +38413,28 @@ package android.se.omapi {
    method public android.se.omapi.Session openSession() throws java.io.IOException;
    method public android.se.omapi.Session openSession() throws java.io.IOException;
  }
  }
  public class SEService {
  public final class SEService {
    ctor public SEService(android.content.Context, android.se.omapi.SEService.SecureElementListener);
    ctor public SEService(android.content.Context, java.util.concurrent.Executor, android.se.omapi.SEService.OnConnectedListener);
    method public android.se.omapi.Reader[] getReaders();
    method public android.se.omapi.Reader[] getReaders();
    method public java.lang.String getVersion();
    method public java.lang.String getVersion();
    method public boolean isConnected();
    method public boolean isConnected();
    method public void shutdown();
    method public void shutdown();
  }
  }
  public static abstract interface SEService.SecureElementListener {
  public static abstract interface SEService.OnConnectedListener {
    method public abstract void onServiceConnected();
    method public abstract void onConnected();
  }
  }
  public class Session {
  public final class Session {
    method public void close();
    method public void close();
    method public void closeChannels();
    method public void closeChannels();
    method public byte[] getATR();
    method public byte[] getATR();
    method public android.se.omapi.Reader getReader();
    method public android.se.omapi.Reader getReader();
    method public boolean isClosed();
    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[], 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[], byte) throws java.io.IOException;
    method public android.se.omapi.Channel openLogicalChannel(byte[]) throws java.io.IOException;
  }
  }
}
}
+9 −9
Original line number Original line Diff line number Diff line
@@ -39,7 +39,7 @@ import java.io.IOException;
 *
 *
 * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
 * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
 */
 */
public class Channel {
public final class Channel implements java.nio.channels.Channel {


    private static final String TAG = "OMAPI.Channel";
    private static final String TAG = "OMAPI.Channel";
    private Session mSession;
    private Session mSession;
@@ -64,7 +64,7 @@ public class Channel {
     * before closing the channel.
     * before closing the channel.
     */
     */
    public void close() {
    public void close() {
        if (!isClosed()) {
        if (isOpen()) {
            synchronized (mLock) {
            synchronized (mLock) {
                try {
                try {
                    mChannel.close();
                    mChannel.close();
@@ -76,21 +76,21 @@ public class Channel {
    }
    }


    /**
    /**
     * Tells if this channel is closed.
     * Tells if this channel is open.
     *
     *
     * @return <code>true</code> if the channel is closed or in case of an error.
     * @return <code>false</code> if the channel is closed or in case of an error.
     *         <code>false</code> otherwise.
     *         <code>true</code> otherwise.
     */
     */
    public boolean isClosed() {
    public boolean isOpen() {
        if (!mService.isConnected()) {
        if (!mService.isConnected()) {
            Log.e(TAG, "service not connected to system");
            Log.e(TAG, "service not connected to system");
            return true;
            return false;
        }
        }
        try {
        try {
            return mChannel.isClosed();
            return !mChannel.isClosed();
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Log.e(TAG, "Exception in isClosed()");
            Log.e(TAG, "Exception in isClosed()");
            return true;
            return false;
        }
        }
    }
    }


+1 −1
Original line number Original line Diff line number Diff line
@@ -37,7 +37,7 @@ import java.io.IOException;
 *
 *
 * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
 * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
 */
 */
public class Reader {
public final class Reader {


    private static final String TAG = "OMAPI.Reader";
    private static final String TAG = "OMAPI.Reader";
    private final String mName;
    private final String mName;
+29 −17
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.Log;


import java.util.HashMap;
import java.util.HashMap;
import java.util.concurrent.Executor;


/**
/**
 * The SEService realises the communication to available Secure Elements on the
 * The SEService realises the communication to available Secure Elements on the
@@ -40,7 +41,7 @@ import java.util.HashMap;
 *
 *
 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API  v3.0</a>
 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API  v3.0</a>
 */
 */
public class SEService {
public final class SEService {


    /**
    /**
     * Error code used with ServiceSpecificException.
     * Error code used with ServiceSpecificException.
@@ -62,11 +63,11 @@ public class SEService {
    /**
    /**
     * Interface to send call-backs to the application when the service is connected.
     * 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.
         * Called by the framework when the service is connected.
         */
         */
        void onServiceConnected();
        void onConnected();
    }
    }


    /**
    /**
@@ -74,16 +75,22 @@ public class SEService {
     * SEService could be bound to the backend.
     * SEService could be bound to the backend.
     */
     */
    private class SEListener extends ISecureElementListener.Stub {
    private class SEListener extends ISecureElementListener.Stub {
        public SecureElementListener mListener = null;
        public OnConnectedListener mListener = null;
        public Executor mExecutor = null;


        @Override
        @Override
        public IBinder asBinder() {
        public IBinder asBinder() {
            return this;
            return this;
        }
        }


        public void onServiceConnected() {
        public void onConnected() {
            if (mListener != null) {
            if (mListener != null && mExecutor != null) {
                mListener.onServiceConnected();
                mExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        mListener.onConnected();
                    }
                });
            }
            }
        }
        }
    }
    }
@@ -116,22 +123,26 @@ public class SEService {
     * the specified listener is called or if isConnected() returns
     * the specified listener is called or if isConnected() returns
     * <code>true</code>. <br>
     * <code>true</code>. <br>
     * The call-back object passed as a parameter will have its
     * The call-back object passed as a parameter will have its
     * onServiceConnected() method called when the connection actually happen.
     * onConnected() method called when the connection actually happen.
     *
     *
     * @param context
     * @param context
     *            the context of the calling application. Cannot be
     *            the context of the calling application. Cannot be
     *            <code>null</code>.
     *            <code>null</code>.
     * @param listener
     * @param listener
     *            a SecureElementListener object.
     *            a OnConnectedListener object.
     * @param executor
     *            an Executor which will be used when invoking the callback.
     */
     */
    public SEService(@NonNull Context context, @NonNull SecureElementListener listener) {
    public SEService(@NonNull Context context, @NonNull Executor executor,
            @NonNull OnConnectedListener listener) {


        if (context == null) {
        if (context == null || listener == null || executor == null) {
            throw new NullPointerException("context must not be null");
            throw new NullPointerException("Arguments must not be null");
        }
        }


        mContext = context;
        mContext = context;
        mSEListener.mListener = listener;
        mSEListener.mListener = listener;
        mSEListener.mExecutor = executor;


        mConnection = new ServiceConnection() {
        mConnection = new ServiceConnection() {


@@ -140,7 +151,7 @@ public class SEService {


                mSecureElementService = ISecureElementService.Stub.asInterface(service);
                mSecureElementService = ISecureElementService.Stub.asInterface(service);
                if (mSEListener != null) {
                if (mSEListener != null) {
                    mSEListener.onServiceConnected();
                    mSEListener.onConnected();
                }
                }
                Log.i(TAG, "Service onServiceConnected");
                Log.i(TAG, "Service onServiceConnected");
            }
            }
@@ -171,12 +182,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.
     * There must be no duplicated objects in the returned list.
     * All available readers shall be listed even if no card is inserted.
     * 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
     * @return An array of Readers. If there are no readers the returned array
     * readers the returned array is of length 0.
     * is of length 0.
     */
     */
    public @NonNull Reader[] getReaders() {
    public @NonNull Reader[] getReaders() {
        if (mSecureElementService == null) {
        if (mSecureElementService == null) {
@@ -212,7 +223,8 @@ public class SEService {
     * (including any binding to an underlying service).
     * (including any binding to an underlying service).
     * As a result isConnected() will return false after shutdown() was called.
     * As a result isConnected() will return false after shutdown() was called.
     * After this method call, the SEService object is not connected.
     * 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.
     * (or part of this application) which is bound to this SEService.
     */
     */
    public void shutdown() {
    public void shutdown() {
+55 −1
Original line number Original line Diff line number Diff line
@@ -39,7 +39,7 @@ import java.util.NoSuchElementException;
 *
 *
 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API  v3.0</a>
 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API  v3.0</a>
 */
 */
public class Session {
public final class Session {


    private final Object mLock = new Object();
    private final Object mLock = new Object();
    private final SEService mService;
    private final SEService mService;
@@ -224,6 +224,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
     * 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
     * the given AID. If the AID is null, which means no Applet is to be selected on this
@@ -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);
    }
}
}