summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Moreland <smoreland@google.com>2022-11-29 23:05:06 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-11-29 23:05:06 +0000
commitcfa266e1b3fa1b653dadf4bf2ae73ecca0a41992 (patch)
tree70ff9b709b8347c86da8ed14690fc7236884e068
parent7939b3ed6ddb0e4879feaf32642403430f86096f (diff)
parent197465aac021002707b5a52230b759313867d7d9 (diff)
downloadSecureElement-cfa266e1b3fa1b653dadf4bf2ae73ecca0a41992.tar.gz
Merge "Terminal: support AIDL" am: 197465aac0main-16k-with-phones
Original change: https://android-review.googlesource.com/c/platform/packages/apps/SecureElement/+/2288034 Change-Id: I1bd426f35e02fb3285f66b937e996d58981ff977 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--Android.bp3
-rw-r--r--src/com/android/se/Terminal.java263
2 files changed, 205 insertions, 61 deletions
diff --git a/Android.bp b/Android.bp
index ee4f8e0..05820b1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -36,7 +36,8 @@ android_app {
certificate: "platform",
static_libs: ["android.hardware.secure_element-V1.0-java",
"android.hardware.secure_element-V1.1-java",
- "android.hardware.secure_element-V1.2-java"],
+ "android.hardware.secure_element-V1.2-java",
+ "android.hardware.secure_element-V1-java"],
optimize: {
enabled: false,
},
diff --git a/src/com/android/se/Terminal.java b/src/com/android/se/Terminal.java
index a3a2b4e..25bb896 100644
--- a/src/com/android/se/Terminal.java
+++ b/src/com/android/se/Terminal.java
@@ -38,6 +38,7 @@ import android.os.Handler;
import android.os.HwBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.se.omapi.ISecureElementListener;
@@ -84,6 +85,7 @@ public class Terminal {
private ISecureElement mSEHal;
private android.hardware.secure_element.V1_2.ISecureElement mSEHal12;
+ private android.hardware.secure_element.ISecureElement mAidlHal;
/** For each Terminal there will be one AccessController object. */
private AccessControlEnforcer mAccessControlEnforcer;
@@ -130,6 +132,24 @@ public class Terminal {
}
};
+ private android.hardware.secure_element.ISecureElementCallback.Stub mAidlCallback =
+ new android.hardware.secure_element.ISecureElementCallback.Stub() {
+ @Override
+ public void onStateChange(boolean state, String debugReason) {
+ stateChange(state, debugReason);
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return super.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return super.HASH;
+ }
+ };
+
private void stateChange(boolean state, String reason) {
synchronized (mLock) {
Log.i(mTag, "OnStateChange:" + state + " reason:" + reason);
@@ -174,9 +194,20 @@ public class Terminal {
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
};
- class SecureElementDeathRecipient implements HwBinder.DeathRecipient {
+ class SecureElementDeathRecipient implements HwBinder.DeathRecipient, Binder.DeathRecipient {
+ // for AIDL
+ @Override
+ public void binderDied() {
+ onDied();
+ }
+
+ // for HIDL
@Override
public void serviceDied(long cookie) {
+ onDied();
+ }
+
+ private void onDied() {
Log.e(mTag, mName + " died");
SecureElementStatsLog.write(
SecureElementStatsLog.SE_STATE_CHANGED,
@@ -194,7 +225,7 @@ public class Terminal {
}
}
- private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient();
+ private SecureElementDeathRecipient mDeathRecipient = new SecureElementDeathRecipient();
private Handler mHandler = new Handler() {
@Override
@@ -240,17 +271,28 @@ public class Terminal {
android.hardware.secure_element.V1_1.ISecureElement mSEHal11 = null;
synchronized (mLock) {
try {
- mSEHal = mSEHal11 = mSEHal12 =
- android.hardware.secure_element.V1_2.ISecureElement.getService(mName,
- retryOnFail);
+ mAidlHal = android.hardware.secure_element.ISecureElement.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(
+ "android.hardware.secure_element.ISecureElement/" + mName));
} catch (Exception e) {
- Log.d(mTag, "SE Hal V1.2 is not supported");
+ Log.d(mTag, "SE AIDL Hal is not supported");
}
- if (mSEHal12 == null) {
+
+ if (mAidlHal == null) {
+ try {
+ mSEHal = mSEHal11 = mSEHal12 =
+ android.hardware.secure_element.V1_2.ISecureElement.getService(
+ mName, retryOnFail);
+ } catch (Exception e) {
+ Log.d(mTag, "SE Hal V1.2 is not supported");
+ }
+ }
+
+ if (mSEHal12 == null && mAidlHal == null) {
try {
mSEHal = mSEHal11 =
- android.hardware.secure_element.V1_1.ISecureElement.getService(mName,
- retryOnFail);
+ android.hardware.secure_element.V1_1.ISecureElement.getService(
+ mName, retryOnFail);
} catch (Exception e) {
Log.d(mTag, "SE Hal V1.1 is not supported");
}
@@ -262,12 +304,16 @@ public class Terminal {
}
}
}
- if (mSEHal11 != null || mSEHal12 != null) {
+ if (mAidlHal != null) {
+ mAidlHal.init(mAidlCallback);
+ mAidlHal.asBinder().linkToDeath(mDeathRecipient, 0);
+ } else if (mSEHal11 != null || mSEHal12 != null) {
mSEHal11.init_1_1(mHalCallback11);
+ mSEHal.linkToDeath(mDeathRecipient, 0);
} else {
mSEHal.init(mHalCallback);
+ mSEHal.linkToDeath(mDeathRecipient, 0);
}
- mSEHal.linkToDeath(mDeathRecipient, 0);
}
Log.i(mTag, mName + " was initialized");
SecureElementStatsLog.write(
@@ -309,7 +355,16 @@ public class Terminal {
synchronized (mLock) {
if (mIsConnected) {
try {
- byte status = mSEHal.closeChannel((byte) channel.getChannelNumber());
+ int status = 0;
+ if (mAidlHal != null) {
+ try {
+ mAidlHal.closeChannel((byte) channel.getChannelNumber());
+ } catch (ServiceSpecificException e) {
+ status = e.errorCode;
+ }
+ } else {
+ status = mSEHal.closeChannel((byte) channel.getChannelNumber());
+ }
/* For Basic Channels, errors are expected.
* Underlying implementations use this call as an indication when there
* aren't any users actively using the channel, and the chip can go
@@ -347,6 +402,13 @@ public class Terminal {
*/
public void close() {
synchronized (mLock) {
+ if (mAidlHal != null) {
+ try {
+ mAidlHal.asBinder().unlinkToDeath(mDeathRecipient, 0);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
if (mSEHal != null) {
try {
mSEHal.unlinkToDeath(mDeathRecipient);
@@ -370,11 +432,19 @@ public class Terminal {
}
try {
- ArrayList<Byte> responseList = mSEHal.getAtr();
- if (responseList.isEmpty()) {
- return null;
+ byte[] atr;
+ if (mAidlHal != null) {
+ atr = mAidlHal.getAtr();
+ if (atr.length == 0) {
+ return null;
+ }
+ } else {
+ ArrayList<Byte> responseList = mSEHal.getAtr();
+ if (responseList.isEmpty()) {
+ return null;
+ }
+ atr = arrayListToByteArray(responseList);
}
- byte[] atr = arrayListToByteArray(responseList);
if (DEBUG) {
Log.i(mTag, "ATR : " + ByteArrayConverter.byteArrayToHexString(atr));
}
@@ -382,6 +452,9 @@ public class Terminal {
} catch (RemoteException e) {
Log.e(mTag, "Exception in getAtr()" + e);
return null;
+ } catch (ServiceSpecificException e) {
+ Log.e(mTag, "Exception in getAtr()" + e);
+ return null;
}
}
@@ -487,23 +560,35 @@ public class Terminal {
}
ArrayList<byte[]> responseList = new ArrayList<byte[]>();
- byte[] status = new byte[1];
+ int[] status = new int[1];
+ status[0] = 0;
- try {
- mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
- new ISecureElement.openBasicChannelCallback() {
- @Override
- public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
- status[0] = halStatus;
- responseList.add(arrayListToByteArray(responseObject));
- return;
- }
- });
- } catch (RemoteException e) {
- throw new IOException(e.getMessage());
+ if (mAidlHal != null) {
+ try {
+ responseList.add(mAidlHal.openBasicChannel(
+ aid == null ? new byte[0] : aid, p2));
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ } catch (ServiceSpecificException e) {
+ status[0] = e.errorCode;
+ }
+ } else {
+ try {
+ mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
+ new ISecureElement.openBasicChannelCallback() {
+ @Override
+ public void onValues(ArrayList<Byte> responseObject,
+ byte halStatus) {
+ status[0] = halStatus;
+ responseList.add(arrayListToByteArray(responseObject));
+ return;
+ }
+ });
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
}
- byte[] selectResponse = responseList.get(0);
if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
return null;
} else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
@@ -514,6 +599,7 @@ public class Terminal {
throw new NoSuchElementException("OpenBasicChannel() failed");
}
+ byte[] selectResponse = responseList.get(0);
Channel basicChannel = new Channel(session, this, 0, selectResponse, aid,
listener);
basicChannel.setChannelAccess(channelAccess);
@@ -577,20 +663,36 @@ public class Terminal {
synchronized (mLock) {
LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
- byte[] status = new byte[1];
+ int[] status = new int[1];
+ status[0] = 0;
- try {
- mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
- new ISecureElement.openLogicalChannelCallback() {
- @Override
- public void onValues(LogicalChannelResponse response, byte halStatus) {
- status[0] = halStatus;
- responseArray[0] = response;
- return;
- }
- });
- } catch (RemoteException e) {
- throw new IOException(e.getMessage());
+ if (mAidlHal != null) {
+ try {
+ responseArray[0] = new LogicalChannelResponse();
+ android.hardware.secure_element.LogicalChannelResponse aidlRs =
+ mAidlHal.openLogicalChannel(aid, p2);
+ responseArray[0].channelNumber = aidlRs.channelNumber;
+ responseArray[0].selectResponse = byteArrayToArrayList(aidlRs.selectResponse);
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ } catch (ServiceSpecificException e) {
+ status[0] = e.errorCode;
+ }
+ } else {
+ try {
+ mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
+ new ISecureElement.openLogicalChannelCallback() {
+ @Override
+ public void onValues(LogicalChannelResponse response,
+ byte halStatus) {
+ status[0] = halStatus;
+ responseArray[0] = response;
+ return;
+ }
+ });
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
}
if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
@@ -628,6 +730,19 @@ public class Terminal {
}
synchronized (mLock) {
+ if (mAidlHal != null) {
+ try {
+ android.hardware.secure_element.LogicalChannelResponse aidlRs =
+ mAidlHal.openLogicalChannel(aid, (byte) 0x00);
+ mAidlHal.closeChannel(aidlRs.channelNumber);
+ } catch (RemoteException e) {
+ return false;
+ } catch (ServiceSpecificException e) {
+ return false;
+ }
+ return true;
+ }
+
LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
byte[] status = new byte[1];
try {
@@ -689,16 +804,31 @@ public class Terminal {
}
private byte[] transmitInternal(byte[] cmd) throws IOException {
- ArrayList<Byte> response;
- try {
- response = mSEHal.transmit(byteArrayToArrayList(cmd));
- } catch (RemoteException e) {
- throw new IOException(e.getMessage());
- }
- if (response.isEmpty()) {
- throw new IOException("Error in transmit()");
+ byte[] rsp;
+ if (mAidlHal != null) {
+ try {
+ rsp = mAidlHal.transmit(cmd);
+ if (rsp.length == 0) {
+ throw new IOException("Error in transmit()");
+ }
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ } catch (ServiceSpecificException e) {
+ throw new IOException(e.getMessage());
+ }
+ } else {
+ ArrayList<Byte> response;
+ try {
+ response = mSEHal.transmit(byteArrayToArrayList(cmd));
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ if (response.isEmpty()) {
+ throw new IOException("Error in transmit()");
+ }
+ rsp = arrayListToByteArray(response);
}
- byte[] rsp = arrayListToByteArray(response);
+
if (DEBUG) {
Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd));
Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp));
@@ -737,7 +867,14 @@ public class Terminal {
*/
public boolean isSecureElementPresent() {
try {
- return mSEHal.isCardPresent();
+ if (mAidlHal != null) {
+ return mAidlHal.isCardPresent();
+ } else {
+ return mSEHal.isCardPresent();
+ }
+ } catch (ServiceSpecificException e) {
+ Log.e(mTag, "Error in isSecureElementPresent() " + e);
+ return false;
} catch (RemoteException e) {
Log.e(mTag, "Error in isSecureElementPresent() " + e);
return false;
@@ -748,7 +885,7 @@ public class Terminal {
* Reset the Secure Element. Return true if success, false otherwise.
*/
public boolean reset() {
- if (mSEHal12 == null) {
+ if (mSEHal12 == null && mAidlHal == null) {
return false;
}
mContext.enforceCallingOrSelfPermission(
@@ -756,13 +893,19 @@ public class Terminal {
"Need SECURE_ELEMENT_PRIVILEGED_OPERATION permission");
try {
- byte status = mSEHal12.reset();
- // Successfully trigger reset. HAL service should send onStateChange
- // after secure element reset and initialization process complete
- if (status == SecureElementStatus.SUCCESS) {
- return true;
+ if (mAidlHal != null) {
+ mAidlHal.reset();
+ } else {
+ byte status = mSEHal12.reset();
+ // Successfully trigger reset. HAL service should send onStateChange
+ // after secure element reset and initialization process complete
+ if (status == SecureElementStatus.SUCCESS) {
+ return true;
+ }
+ Log.e(mTag, "Error resetting terminal " + mName);
}
- Log.e(mTag, "Error reseting terminal " + mName);
+ } catch (ServiceSpecificException e) {
+ Log.e(mTag, "Exception in reset()" + e);
} catch (RemoteException e) {
Log.e(mTag, "Exception in reset()" + e);
}