Snap for 4716599 from 0f8b45235b612ac4d7a9cd7af7233039e4358b81 to pi-release
Change-Id: I5ade2e643b33883ac380ecac10c4822d15232b89
diff --git a/src/com/android/se/SecureElementService.java b/src/com/android/se/SecureElementService.java
index 20f0524..b38cb22 100644
--- a/src/com/android/se/SecureElementService.java
+++ b/src/com/android/se/SecureElementService.java
@@ -26,7 +26,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.hardware.secure_element.V1_0.ISecureElement;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -101,7 +100,6 @@
}
}
};
- private Context mContext;
public SecureElementService() {
super();
@@ -134,8 +132,6 @@
@Override
public void onCreate() {
Log.i(mTag, Thread.currentThread().getName() + " onCreate");
-
- mContext = getApplicationContext();
createTerminals();
ServiceManager.addService(Context.SECURE_ELEMENT_SERVICE, mSecureElementServiceBinder);
}
@@ -148,33 +144,31 @@
Log.i(mTag, "onDestroy");
for (Terminal terminal : mTerminals.values()) {
terminal.closeChannels();
+ terminal.close();
}
}
private void addTerminals(String terminalName) {
int index = 1;
- String name = terminalName + Integer.toString(index);
+ String name = null;
try {
- ISecureElement seHal = ISecureElement.getService(name);
- while (seHal != null) {
- Terminal terminal = new Terminal(name, mContext, seHal);
- mTerminals.put(name, terminal);
- index++;
+ do {
name = terminalName + Integer.toString(index);
- seHal = ISecureElement.getService(name);
- }
+ Terminal terminal = new Terminal(name, this);
+ terminal.initialize();
+ mTerminals.put(name, terminal);
+ } while (++index > 0);
} catch (NoSuchElementException e) {
- //Thrown if the HAL implementation doesn't exist.
- } catch (RemoteException e) {
+ Log.i(mTag, "No HAL implementation for " + name);
+ } catch (RemoteException | RuntimeException e) {
Log.e(mTag, "Error in getService() for " + name);
}
}
private void createTerminals() {
- // Check for all eSE HAL implementations
+ // Check for all SE HAL implementations
addTerminals(ESE_TERMINAL);
addTerminals(UICC_TERMINAL);
- return;
}
private String getPackageNameFromCallingUid(int uid) {
diff --git a/src/com/android/se/Terminal.java b/src/com/android/se/Terminal.java
index ee42502..b3bedba 100644
--- a/src/com/android/se/Terminal.java
+++ b/src/com/android/se/Terminal.java
@@ -30,6 +30,9 @@
import android.hardware.secure_element.V1_0.LogicalChannelResponse;
import android.hardware.secure_element.V1_0.SecureElementStatus;
import android.os.Build;
+import android.os.Handler;
+import android.os.HwBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.se.omapi.ISecureElementListener;
@@ -67,6 +70,8 @@
private boolean mDefaultApplicationSelectedOnBasicChannel = true;
private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+ private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000;
+ private static final int EVENT_GET_HAL = 1;
private ISecureElement mSEHal;
@@ -84,31 +89,80 @@
mAccessControlEnforcer.reset();
}
} else {
+ // If any logical channel in use is in the channel list, it should be closed
+ // because the access control enfocer allowed to open it by checking the access
+ // rules retrieved before. Now we are going to retrieve the rules again and
+ // the new rules can be different from the previous ones.
+ closeChannels();
try {
initializeAccessControl();
} catch (Exception e) {
// ignore
}
- synchronized (mLock) {
- mDefaultApplicationSelectedOnBasicChannel = true;
- }
+ mDefaultApplicationSelectedOnBasicChannel = true;
}
}
}
};
- public Terminal(String name, Context context, ISecureElement seHal) {
- if (seHal == null) {
- throw new IllegalArgumentException("ISecureElement cannot be null ");
+ class SecureElementDeathRecipient implements HwBinder.DeathRecipient {
+ @Override
+ public void serviceDied(long cookie) {
+ Log.e(mTag, mName + " died");
+ synchronized (mLock) {
+ mIsConnected = false;
+ if (mAccessControlEnforcer != null) {
+ mAccessControlEnforcer.reset();
+ }
+ }
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0),
+ GET_SERVICE_DELAY_MILLIS);
}
+ }
+
+ private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient();
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case EVENT_GET_HAL:
+ try {
+ initialize();
+ } catch (Exception e) {
+ Log.e(mTag, mName + " could not be initialized again");
+ sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0),
+ GET_SERVICE_DELAY_MILLIS);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ public Terminal(String name, Context context) {
mContext = context;
mName = name;
mTag = "SecureElement-Terminal-" + getName();
- mSEHal = seHal;
- try {
- seHal.init(mHalCallback);
- } catch (RemoteException e) {
+ }
+
+ /**
+ * Initializes the terminal
+ *
+ * @throws NoSuchElementException if there is no HAL implementation for the specified SE name
+ * @throws RemoteException if there is a failure communicating with the remote
+ */
+ public void initialize() throws NoSuchElementException, RemoteException {
+ synchronized (mLock) {
+ mSEHal = ISecureElement.getService(mName);
+ if (mSEHal == null) {
+ throw new NoSuchElementException("No HAL is provided for " + mName);
+ }
+ mSEHal.init(mHalCallback);
+ mSEHal.linkToDeath(mDeathRecipient, 0);
}
+ Log.i(mTag, mName + " was initialized");
}
private ArrayList<Byte> byteArrayToArrayList(byte[] array) {
@@ -164,14 +218,28 @@
}
/**
- * This method is called in SecureElementService:onDestroy to clean up
- * all open channels.
+ * Cleans up all the channels in use.
*/
public synchronized void closeChannels() {
Collection<Channel> col = mChannels.values();
Channel[] channelList = col.toArray(new Channel[col.size()]);
for (Channel channel : channelList) {
- closeChannel(channel);
+ channel.close();
+ }
+ }
+
+ /**
+ * Closes the terminal.
+ */
+ public void close() {
+ synchronized (mLock) {
+ if (mSEHal != null) {
+ try {
+ mSEHal.unlinkToDeath(mDeathRecipient);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
}
}