Add new APIs iccExchangeSimIO and iccTransmitApduBasicChannel to TelephonyManager.
The new APIs are needed to support SEEK.
Also modifies TelephonyManager.iccOpenLogicalChannel to return the status of
the command.
Change-Id: Iff2674fb0e23210f2579cb883e64571347ade5e6
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 3ae99e7..02a9c1f 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -39,6 +39,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CellInfo;
+import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.NeighboringCellInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -92,8 +93,8 @@
private static final int CMD_ANSWER_RINGING_CALL = 4;
private static final int CMD_END_CALL = 5; // not used yet
private static final int CMD_SILENCE_RINGER = 6;
- private static final int CMD_TRANSMIT_APDU = 7;
- private static final int EVENT_TRANSMIT_APDU_DONE = 8;
+ private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
+ private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
private static final int CMD_OPEN_CHANNEL = 9;
private static final int EVENT_OPEN_CHANNEL_DONE = 10;
private static final int CMD_CLOSE_CHANNEL = 11;
@@ -116,6 +117,10 @@
private static final int EVENT_SET_CDMA_SUBSCRIPTION_DONE = 28;
private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 29;
private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 30;
+ private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 31;
+ private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 32;
+ private static final int CMD_EXCHANGE_SIM_IO = 33;
+ private static final int EVENT_EXCHANGE_SIM_IO_DONE = 34;
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
@@ -199,6 +204,7 @@
Message onCompleted;
AsyncResult ar;
UiccCard uiccCard = UiccController.getInstance().getUiccCard();
+ IccAPDUArgument iccArgument;
switch (msg.what) {
case CMD_HANDLE_PIN_MMI:
@@ -262,9 +268,9 @@
}
break;
- case CMD_TRANSMIT_APDU:
+ case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
request = (MainThreadRequest) msg.obj;
- IccAPDUArgument argument = (IccAPDUArgument) request.argument;
+ iccArgument = (IccAPDUArgument) request.argument;
if (uiccCard == null) {
loge("iccTransmitApduLogicalChannel: No UICC");
request.result = new IccIoResult(0x6F, 0, (byte[])null);
@@ -272,15 +278,16 @@
request.notifyAll();
}
} else {
- onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_DONE, request);
+ onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
+ request);
uiccCard.iccTransmitApduLogicalChannel(
- argument.channel, argument.cla, argument.command,
- argument.p1, argument.p2, argument.p3, argument.data,
+ iccArgument.channel, iccArgument.cla, iccArgument.command,
+ iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
onCompleted);
}
break;
- case EVENT_TRANSMIT_APDU_DONE:
+ case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
if (ar.exception == null && ar.result != null) {
@@ -301,6 +308,76 @@
}
break;
+ case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
+ request = (MainThreadRequest) msg.obj;
+ iccArgument = (IccAPDUArgument) request.argument;
+ if (uiccCard == null) {
+ loge("iccTransmitApduBasicChannel: No UICC");
+ request.result = new IccIoResult(0x6F, 0, (byte[])null);
+ synchronized (request) {
+ request.notifyAll();
+ }
+ } else {
+ onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
+ request);
+ uiccCard.iccTransmitApduBasicChannel(
+ iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
+ iccArgument.p3, iccArgument.data, onCompleted);
+ }
+ break;
+
+ case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ request.result = new IccIoResult(0x6F, 0, (byte[])null);
+ if (ar.result == null) {
+ loge("iccTransmitApduBasicChannel: Empty response");
+ } else if (ar.exception instanceof CommandException) {
+ loge("iccTransmitApduBasicChannel: CommandException: " +
+ ar.exception);
+ } else {
+ loge("iccTransmitApduBasicChannel: Unknown exception");
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_EXCHANGE_SIM_IO:
+ request = (MainThreadRequest) msg.obj;
+ iccArgument = (IccAPDUArgument) request.argument;
+ if (uiccCard == null) {
+ loge("iccExchangeSimIO: No UICC");
+ request.result = new IccIoResult(0x6F, 0, (byte[])null);
+ synchronized (request) {
+ request.notifyAll();
+ }
+ } else {
+ onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
+ request);
+ uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
+ iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
+ iccArgument.data, onCompleted);
+ }
+ break;
+
+ case EVENT_EXCHANGE_SIM_IO_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ request.result = new IccIoResult(0x6f, 0, (byte[])null);
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
case CMD_SEND_ENVELOPE:
request = (MainThreadRequest) msg.obj;
if (uiccCard == null) {
@@ -353,18 +430,37 @@
case EVENT_OPEN_CHANNEL_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
+ IccOpenLogicalChannelResponse openChannelResp;
if (ar.exception == null && ar.result != null) {
- request.result = ((int[]) ar.result)[0];
+ int[] result = (int[]) ar.result;
+ int channelId = result[0];
+ byte[] selectResponse = null;
+ if (result.length > 1) {
+ selectResponse = new byte[result.length - 1];
+ for (int i = 1; i < result.length; ++i) {
+ selectResponse[i - 1] = (byte) result[i];
+ }
+ }
+ openChannelResp = new IccOpenLogicalChannelResponse(channelId,
+ IccOpenLogicalChannelResponse.NO_ERROR, selectResponse );
} else {
- request.result = -1;
if (ar.result == null) {
loge("iccOpenLogicalChannel: Empty response");
- } else if (ar.exception instanceof CommandException) {
- loge("iccOpenLogicalChannel: CommandException: " +
- ar.exception);
- } else {
- loge("iccOpenLogicalChannel: Unknown exception");
}
+ if (ar.exception != null) {
+ loge("iccOpenLogicalChannel: Exception: " + ar.exception);
+ }
+
+ int errorCode = IccOpenLogicalChannelResponse.UNKNOWN_ERROR;
+ if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
+ if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
+ errorCode = IccOpenLogicalChannelResponse.MISSING_RESOURCE;
+ } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
+ errorCode = IccOpenLogicalChannelResponse.NO_SUCH_ELEMENT;
+ }
+ }
+ openChannelResp = new IccOpenLogicalChannelResponse(
+ IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
}
synchronized (request) {
request.notifyAll();
@@ -1468,13 +1564,14 @@
}
@Override
- public int iccOpenLogicalChannel(String AID) {
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
enforceModifyPermissionOrCarrierPrivilege();
if (DBG) log("iccOpenLogicalChannel: " + AID);
- Integer channel = (Integer)sendRequest(CMD_OPEN_CHANNEL, AID);
- if (DBG) log("iccOpenLogicalChannel: " + channel);
- return channel;
+ IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
+ CMD_OPEN_CHANNEL, AID);
+ if (DBG) log("iccOpenLogicalChannel: " + response);
+ return response;
}
@Override
@@ -1505,7 +1602,7 @@
return "";
}
- IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU,
+ IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
if (DBG) log("iccTransmitApduLogicalChannel: " + response);
@@ -1523,6 +1620,66 @@
}
@Override
+ public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
+ int p3, String data) {
+ enforceModifyPermissionOrCarrierPrivilege();
+
+ if (DBG) {
+ log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
+ + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
+ }
+
+ IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
+ new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
+ if (DBG) log("iccTransmitApduBasicChannel: " + response);
+
+ // If the payload is null, there was an error. Indicate that by returning
+ // an empty string.
+ if (response.payload == null) {
+ return "";
+ }
+
+ // Append the returned status code to the end of the response payload.
+ String s = Integer.toHexString(
+ (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
+ s = IccUtils.bytesToHexString(response.payload) + s;
+ return s;
+ }
+
+ @Override
+ public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+ String filePath) {
+ enforceModifyPermissionOrCarrierPrivilege();
+
+ if (DBG) {
+ log("Exchange SIM_IO " + fileID + ":" + command + " " +
+ p1 + " " + p2 + " " + p3 + ":" + filePath);
+ }
+
+ IccIoResult response =
+ (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
+ new IccAPDUArgument(fileID, command, -1, p1, p2, p3, filePath));
+
+ if (DBG) {
+ log("Exchange SIM_IO [R]" + response);
+ }
+
+ byte[] result = null;
+ int length = 2;
+ if (response.payload != null) {
+ length = 2 + response.payload.length;
+ result = new byte[length];
+ System.arraycopy(response.payload, 0, result, 0, response.payload.length);
+ } else {
+ result = new byte[length];
+ }
+
+ result[length - 1] = (byte) response.sw2;
+ result[length - 2] = (byte) response.sw1;
+ return result;
+ }
+
+ @Override
public String sendEnvelopeWithStatus(String content) {
enforceModifyPermissionOrCarrierPrivilege();