resolved conflicts for merge of d50129c8 to master-nova
Change-Id: I5598068713c0cc33c2a281928ccfc57c71839d59
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 145f9a7..74bc9b7 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -40,15 +40,18 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.telephony.CallManager;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.DefaultPhoneNotifier;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IThirdPartyCallProvider;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.CallManager;
-import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.thirdpartyphone.ThirdPartyPhone;
+import com.android.internal.telephony.uicc.IccIoResult;
+import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.uicc.UiccController;
import java.util.List;
import java.util.ArrayList;
@@ -68,7 +71,13 @@
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_NEW_INCOMING_THIRD_PARTY_CALL = 7;
+ private static final int CMD_TRANSMIT_APDU = 7;
+ private static final int EVENT_TRANSMIT_APDU_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;
+ private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
+ private static final int CMD_NEW_INCOMING_THIRD_PARTY_CALL = 13;
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
@@ -81,6 +90,25 @@
CallHandlerServiceProxy mCallHandlerService;
/**
+ * A request object to use for transmitting data to an ICC.
+ */
+ private static final class IccAPDUArgument {
+ public int channel, cla, command, p1, p2, p3;
+ public String data;
+
+ public IccAPDUArgument(int channel, int cla, int command,
+ int p1, int p2, int p3, String data) {
+ this.channel = channel;
+ this.cla = cla;
+ this.command = command;
+ this.p1 = p1;
+ this.p2 = p2;
+ this.p3 = p3;
+ this.data = data;
+ }
+ }
+
+ /**
* A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
* request after sending. The main thread will notify the request when it is complete.
*/
@@ -189,6 +217,7 @@
request.notifyAll();
}
break;
+
case CMD_NEW_INCOMING_THIRD_PARTY_CALL: {
request = (MainThreadRequest) msg.obj;
IncomingThirdPartyCallArgs args = (IncomingThirdPartyCallArgs) request.argument;
@@ -198,6 +227,95 @@
break;
}
+ case CMD_TRANSMIT_APDU:
+ request = (MainThreadRequest) msg.obj;
+ IccAPDUArgument argument = (IccAPDUArgument) request.argument;
+ onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_DONE, request);
+ UiccController.getInstance().getUiccCard().iccTransmitApduLogicalChannel(
+ argument.channel, argument.cla, argument.command,
+ argument.p1, argument.p2, argument.p3, argument.data,
+ onCompleted);
+ break;
+
+ case EVENT_TRANSMIT_APDU_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("iccTransmitApduLogicalChannel: Empty response");
+ } else if (ar.exception != null &&
+ (ar.exception instanceof CommandException)) {
+ loge("iccTransmitApduLogicalChannel: CommandException: " +
+ (CommandException)ar.exception);
+ } else {
+ loge("iccTransmitApduLogicalChannel: Unknown exception");
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_OPEN_CHANNEL:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
+ UiccController.getInstance().getUiccCard().iccOpenLogicalChannel(
+ (String)request.argument, onCompleted);
+ break;
+
+ case EVENT_OPEN_CHANNEL_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = new Integer(((int[])ar.result)[0]);
+ } else {
+ request.result = new Integer(-1);
+ if (ar.result == null) {
+ loge("iccOpenLogicalChannel: Empty response");
+ } else if (ar.exception != null &&
+ (ar.exception instanceof CommandException)) {
+ loge("iccOpenLogicalChannel: CommandException: " +
+ (CommandException)ar.exception);
+ } else {
+ loge("iccOpenLogicalChannel: Unknown exception");
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_CLOSE_CHANNEL:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE,
+ request);
+ UiccController.getInstance().getUiccCard().iccCloseLogicalChannel(
+ ((Integer)request.argument).intValue(),
+ onCompleted);
+ break;
+
+ case EVENT_CLOSE_CHANNEL_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null) {
+ request.result = new Boolean(true);
+ } else {
+ request.result = new Boolean(false);
+ if (ar.exception instanceof CommandException) {
+ loge("iccCloseLogicalChannel: CommandException: " +
+ (CommandException)ar.exception);
+ } else {
+ loge("iccCloseLogicalChannel: Unknown exception");
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -730,7 +848,7 @@
cells = (ArrayList<NeighboringCellInfo>) sendRequest(
CMD_HANDLE_NEIGHBORING_CELL, null);
} catch (RuntimeException e) {
- Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
+ loge("getNeighboringCellInfo " + e);
}
return cells;
} else {
@@ -842,6 +960,14 @@
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
}
+ /**
+ * Make sure the caller has SIM_COMMUNICATION permission.
+ *
+ * @throws SecurityException if the caller does not have the required permission.
+ */
+ private void enforceSimCommunicationPermission() {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.SIM_COMMUNICATION, null);
+ }
private String createTelUrl(String number) {
if (TextUtils.isEmpty(number)) {
@@ -1017,4 +1143,60 @@
Settings.System.WHEN_TO_MAKE_WIFI_CALLS, setting);
if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + setting);
}
+
+ @Override
+ public int iccOpenLogicalChannel(String AID) {
+ enforceSimCommunicationPermission();
+
+ if (DBG) log("iccOpenLogicalChannel: " + AID);
+ Integer channel = (Integer)sendRequest(CMD_OPEN_CHANNEL, AID);
+ if (DBG) log("iccOpenLogicalChannel: " + channel);
+ return channel.intValue();
+ }
+
+ @Override
+ public boolean iccCloseLogicalChannel(int channel) {
+ enforceSimCommunicationPermission();
+
+ if (DBG) log("iccCloseLogicalChannel: " + channel);
+ if (channel < 0) {
+ return false;
+ }
+ Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL,
+ new Integer(channel));
+ if (DBG) log("iccCloseLogicalChannel: " + success);
+ return success;
+ }
+
+ @Override
+ public String iccTransmitApduLogicalChannel(int channel, int cla,
+ int command, int p1, int p2, int p3, String data) {
+ enforceSimCommunicationPermission();
+
+ if (DBG) {
+ log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
+ " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
+ " data=" + data);
+ }
+
+ if (channel < 0) {
+ return "";
+ }
+
+ IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU,
+ new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
+ if (DBG) log("iccTransmitApduLogicalChannel: " + 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;
+ }
}