Loading android/app/src/com/android/bluetooth/sap/SapMessage.java +46 −78 Original line number Diff line number Diff line package com.android.bluetooth.sap; import android.hardware.radio.V1_0.ISap; import android.hardware.radio.V1_0.SapApduType; import android.hardware.radio.V1_0.SapTransferProtocol; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -153,7 +157,7 @@ public class SapMessage { static AtomicInteger sNextSerial = new AtomicInteger(1); // Map<rilSerial, RequestType> - HashTable is synchronized private static Map<Integer, Integer> sOngoingRequests = new Hashtable<Integer, Integer>(); static Map<Integer, Integer> sOngoingRequests = new Hashtable<Integer, Integer>(); private boolean mSendToRil = false; // set to true for messages that needs to go to the RIL private boolean mClearRilQueue = false; /* set to true for messages that needs to cause the sOngoingRequests to be cleared. */ Loading Loading @@ -704,139 +708,103 @@ public class SapMessage { dataLength[3] = (byte)((length) & 0xff); out.writeRawBytes(dataLength); } private ArrayList<Byte> primitiveArrayToContainerArrayList(byte[] arr) { ArrayList<Byte> arrayList = new ArrayList<>(arr.length); for (byte b : arr) { arrayList.add(b); } return arrayList; } /** * Write this SAP message as a rild compatible protobuf message. * Solicited Requests are formed as follows: * int type - the rild-bt type * int serial - an number incrementing for each message. * Send the message by calling corresponding ISap api. */ public void writeReqToStream(CodedOutputStreamMicro out) throws IOException { public void send(ISap sapProxy) throws Exception { int rilSerial = sNextSerial.getAndIncrement(); SapApi.MsgHeader msg = new MsgHeader(); /* Common variables for all requests */ msg.setToken(rilSerial); msg.setType(SapApi.REQUEST); msg.setError(SapApi.RIL_E_UNUSED); Log.e(TAG, "callISapReq: called for mMsgType " + mMsgType + " rilSerial " + rilSerial); /* Update the ongoing requests queue */ if (mClearRilQueue == true) { resetPendingRilMessages(); } // No need to synchronize this, as the HashList is already doing this. sOngoingRequests.put(rilSerial, mMsgType); switch(mMsgType) { case ID_CONNECT_REQ: { SapApi.RIL_SIM_SAP_CONNECT_REQ reqMsg = new RIL_SIM_SAP_CONNECT_REQ(); reqMsg.setMaxMessageSize(mMaxMsgSize); msg.setId(SapApi.RIL_SIM_SAP_CONNECT); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.connectReq(rilSerial, mMaxMsgSize); break; } case ID_DISCONNECT_REQ: { SapApi.RIL_SIM_SAP_DISCONNECT_REQ reqMsg = new RIL_SIM_SAP_DISCONNECT_REQ(); msg.setId(SapApi.RIL_SIM_SAP_DISCONNECT); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.disconnectReq(rilSerial); break; } case ID_TRANSFER_APDU_REQ: { SapApi.RIL_SIM_SAP_APDU_REQ reqMsg = new RIL_SIM_SAP_APDU_REQ(); msg.setId(SapApi.RIL_SIM_SAP_APDU); int type; ArrayList<Byte> command; if(mApdu != null) { reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU); reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu)); type = SapApduType.APDU; command = primitiveArrayToContainerArrayList(mApdu); } else if (mApdu7816 != null) { reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU7816); reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu7816)); type = SapApduType.APDU7816; command = primitiveArrayToContainerArrayList(mApdu7816); } else { Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ"); throw new IllegalArgumentException(); } msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.apduReq(rilSerial, type, command); break; } case ID_SET_TRANSPORT_PROTOCOL_REQ: { SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ reqMsg = new RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ(); msg.setId(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL); int transportProtocol; if(mTransportProtocol == TRANS_PROTO_T0) { reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t0); transportProtocol = SapTransferProtocol.T0; } else if(mTransportProtocol == TRANS_PROTO_T1) { reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t1); transportProtocol = SapTransferProtocol.T1; } else { Log.e(TAG, "Missing or invalid TransportProtocol parameter in"+ " SET_TRANSPORT_PROTOCOL_REQ: "+ mTransportProtocol ); Log.e(TAG, "Missing or invalid TransportProtocol parameter in" + " SET_TRANSPORT_PROTOCOL_REQ: " + mTransportProtocol); throw new IllegalArgumentException(); } msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.setTransferProtocolReq(rilSerial, transportProtocol); break; } case ID_TRANSFER_ATR_REQ: { SapApi.RIL_SIM_SAP_TRANSFER_ATR_REQ reqMsg = new RIL_SIM_SAP_TRANSFER_ATR_REQ(); msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_ATR); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.transferAtrReq(rilSerial); break; } case ID_POWER_SIM_OFF_REQ: { SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ(); msg.setId(SapApi.RIL_SIM_SAP_POWER); reqMsg.setState(false); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.powerReq(rilSerial, false); break; } case ID_POWER_SIM_ON_REQ: { SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ(); msg.setId(SapApi.RIL_SIM_SAP_POWER); reqMsg.setState(true); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.powerReq(rilSerial, true); break; } case ID_RESET_SIM_REQ: { SapApi.RIL_SIM_SAP_RESET_SIM_REQ reqMsg = new RIL_SIM_SAP_RESET_SIM_REQ(); msg.setId(SapApi.RIL_SIM_SAP_RESET_SIM); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.resetSimReq(rilSerial); break; } case ID_TRANSFER_CARD_READER_STATUS_REQ: { SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ reqMsg = new RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ(); msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.transferCardReaderStatusReq(rilSerial); break; } default: Log.e(TAG, "Unknown request type"); throw new IllegalArgumentException(); } /* Update the ongoing requests queue */ if(mClearRilQueue == true) { resetPendingRilMessages(); } // No need to synchronize this, as the HashList is already doing this. sOngoingRequests.put(rilSerial, mMsgType); out.flush(); if (VERBOSE) Log.e(TAG, "callISapReq: done without exceptions"); } public static SapMessage newInstance(MsgHeader msg) throws IOException { Loading android/app/src/com/android/bluetooth/sap/SapRilReceiver.java +165 −0 Original line number Diff line number Diff line Loading @@ -2,12 +2,17 @@ package com.android.bluetooth.sap; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.android.btsap.SapApi.MsgHeader; import com.google.protobuf.micro.CodedInputStreamMicro; import com.google.protobuf.micro.CodedOutputStreamMicro; import android.hardware.radio.V1_0.ISap; import android.hardware.radio.V1_0.ISapCallback; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.Handler; Loading @@ -27,15 +32,175 @@ public class SapRilReceiver implements Runnable { LocalSocket mSocket = null; CodedOutputStreamMicro mRilBtOutStream = null; InputStream mRilBtInStream = null; SapCallback mSapCallback; ISap mSapProxy; private Handler mSapServerMsgHandler = null; private Handler mSapServiceHandler = null; public static final int RIL_MAX_COMMAND_BYTES = (8 * 1024); byte[] buffer = new byte[RIL_MAX_COMMAND_BYTES]; private void sendSapMessage(SapMessage sapMessage) { if (sapMessage.getMsgType() < SapMessage.ID_RIL_BASE) { sendClientMessage(sapMessage); } else { sendRilIndMessage(sapMessage); } } private void removeOngoingReqAndSendMessage(int token, SapMessage sapMessage) { Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "removeOngoingReqAndSendMessage: token " + token + " reqType " + (reqType == null ? "null" : SapMessage.getMsgTypeName(reqType))); } sendSapMessage(sapMessage); } class SapCallback extends ISapCallback.Stub { public void connectResponse(int token, int sapConnectRsp, int maxMsgSize) { Log.d(TAG, "connectResponse: token " + token + " sapConnectRsp " + sapConnectRsp + " maxMsgSize " + maxMsgSize); SapMessage sapMessage = new SapMessage(SapMessage.ID_CONNECT_RESP); sapMessage.setConnectionStatus(sapConnectRsp); if (sapConnectRsp == SapMessage.CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED) { sapMessage.setMaxMsgSize(maxMsgSize); } sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); } public void disconnectResponse(int token) { Log.d(TAG, "disconnectResponse: token " + token); SapMessage sapMessage = new SapMessage(SapMessage.ID_DISCONNECT_RESP); sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); } public void disconnectIndication(int token, int disconnectType) { Log.d(TAG, "disconnectIndication: token " + token + " disconnectType " + disconnectType); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNSOL_DISCONNECT_IND); sapMessage.setDisconnectionType(disconnectType); sendSapMessage(sapMessage); } public void apduResponse(int token, int resultCode, ArrayList<Byte> apduRsp) { Log.d(TAG, "apduResponse: token " + token); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_APDU_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setApduResp(arrayListToPrimitiveArray(apduRsp)); } removeOngoingReqAndSendMessage(token, sapMessage); } public void transferAtrResponse(int token, int resultCode, ArrayList<Byte> atr) { Log.d(TAG, "transferAtrResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_ATR_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setAtr(arrayListToPrimitiveArray(atr)); } removeOngoingReqAndSendMessage(token, sapMessage); } public void powerResponse(int token, int resultCode) { Log.d(TAG, "powerResponse: token " + token + " resultCode " + resultCode); Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "powerResponse: reqType " + (reqType == null ? "null" : SapMessage.getMsgTypeName(reqType))); } SapMessage sapMessage; if (reqType == SapMessage.ID_POWER_SIM_OFF_REQ) { sapMessage = new SapMessage(SapMessage.ID_POWER_SIM_OFF_RESP); } else if (reqType == SapMessage.ID_POWER_SIM_ON_REQ) { sapMessage = new SapMessage(SapMessage.ID_POWER_SIM_ON_RESP); } else { return; } sapMessage.setResultCode(resultCode); sendSapMessage(sapMessage); } public void resetSimResponse(int token, int resultCode) { Log.d(TAG, "resetSimResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_RESET_SIM_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); } public void statusIndication(int token, int status) { Log.d(TAG, "statusIndication: token " + token + " status " + status); SapMessage sapMessage = new SapMessage(SapMessage.ID_STATUS_IND); sapMessage.setStatusChange(status); sendSapMessage(sapMessage); } public void transferCardReaderStatusResponse( int token, int resultCode, int cardReaderStatus) { Log.d(TAG, "transferCardReaderStatusResponse: token " + token + " resultCode " + resultCode + " cardReaderStatus " + cardReaderStatus); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_CARD_READER_STATUS_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setCardReaderStatus(cardReaderStatus); } removeOngoingReqAndSendMessage(token, sapMessage); } public void errorResponse(int token) { Log.d(TAG, "errorResponse: token " + token); // Since ERROR_RESP isn't supported by createUnsolicited(), keeping behavior same here // SapMessage sapMessage = new SapMessage(SapMessage.ID_ERROR_RESP); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNKNOWN); sendSapMessage(sapMessage); } public void transferProtocolResponse(int token, int resultCode) { Log.d(TAG, "transferProtocolResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_SET_TRANSPORT_PROTOCOL_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); } } public static byte[] arrayListToPrimitiveArray(List<Byte> bytes) { byte[] ret = new byte[bytes.size()]; for (int i = 0; i < ret.length; i++) { ret[i] = bytes.get(i); } return ret; } public ISap getSapProxy() { if (mSapProxy != null) { return mSapProxy; } try { mSapProxy = ISap.getService(SOCKET_NAME_RIL_BT); if (mSapProxy != null) { Log.d(TAG, "getSapProxy: mSapProxy != null; calling setCallback()"); // todo(b/31632518): need to do this again if remote process crashes/restarts mSapProxy.setCallback(mSapCallback); } else { Log.e(TAG, "getSapProxy: mSapProxy == null"); } } catch (Exception e) { Log.e(TAG, "getSapProxy: exception", e); } return mSapProxy; } public SapRilReceiver(Handler SapServerMsgHandler, Handler sapServiceHandler) { mSapServerMsgHandler = SapServerMsgHandler; mSapServiceHandler = sapServiceHandler; mSapCallback = new SapCallback(); mSapProxy = getSapProxy(); } /** Loading android/app/src/com/android/bluetooth/sap/SapServer.java +20 −14 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.radio.V1_0.ISap; import android.os.Handler; import android.os.Handler.Callback; import android.os.HandlerThread; Loading @@ -20,7 +21,6 @@ import android.telephony.TelephonyManager; import android.util.Log; import com.android.bluetooth.R; import com.google.protobuf.micro.CodedOutputStreamMicro; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; Loading Loading @@ -58,8 +58,6 @@ public class SapServer extends Thread implements Callback { /* RFCOMM socket I/O streams */ private BufferedOutputStream mRfcommOut = null; private BufferedInputStream mRfcommIn = null; /* The RIL output stream - the input stream is owned by the SapRilReceiver object */ private CodedOutputStreamMicro mRilBtOutStream = null; /* References to the SapRilReceiver object */ private SapRilReceiver mRilBtReceiver = null; private Thread mRilBtReceiverThread = null; Loading Loading @@ -313,9 +311,12 @@ public class SapServer extends Thread implements Callback { while (!done) { if(VERBOSE) Log.i(TAG, "Waiting for incomming RFCOMM message..."); int requestType = mRfcommIn.read(); if (VERBOSE) Log.i(TAG, "RFCOMM message read..."); if(requestType == -1) { if (VERBOSE) Log.i(TAG, "requestType == -1"); done = true; // EOF reached } else { if (VERBOSE) Log.i(TAG, "requestType != -1"); SapMessage msg = SapMessage.readMessage(requestType, mRfcommIn); /* notify about an incoming message from the BT Client */ SapService.notifyUpdateWakeLock(mSapServiceHandler); Loading Loading @@ -582,7 +583,6 @@ public class SapServer extends Thread implements Callback { } } /************************************************************************* * SAP Server Message Handler Thread Functions *************************************************************************/ Loading @@ -609,7 +609,6 @@ public class SapServer extends Thread implements Callback { case SAP_MSG_RIL_CONNECT: /* The connection to rild-bt have been established. Store the outStream handle * and send the connect request. */ mRilBtOutStream = mRilBtReceiver.getRilBtOutStream(); if(mTestMode != SapMessage.INVALID_VALUE) { SapMessage rilTestModeReq = new SapMessage(SapMessage.ID_RIL_SIM_ACCESS_TEST_REQ); rilTestModeReq.setTestMode(mTestMode); Loading Loading @@ -845,17 +844,24 @@ public class SapServer extends Thread implements Callback { private void sendRilMessage(SapMessage sapMsg) { if(VERBOSE) Log.i(TAG_HANDLER, "sendRilMessage() - " + SapMessage.getMsgTypeName(sapMsg.getMsgType())); try { if(mRilBtOutStream != null) { sapMsg.writeReqToStream(mRilBtOutStream); } /* Else SAP was enabled on a build that did not support SAP, which we will not * handle. */ } catch (IOException e) { Log.e(TAG_HANDLER, "Unable to send message to RIL", e); Log.d(TAG_HANDLER, "sendRilMessage: calling getSapProxy"); ISap sapProxy = mRilBtReceiver.getSapProxy(); if (sapProxy == null) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); sendClientMessage(errorReply); } catch (IllegalArgumentException e) { Log.e(TAG_HANDLER, "Unable encode message", e); return; } try { sapMsg.send(sapProxy); if (VERBOSE) { Log.d(TAG_HANDLER, "sendRilMessage: sapMsg.callISapReq called " + "successfully"); } } catch (Exception e) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL", e); SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); sendClientMessage(errorReply); } Loading Loading
android/app/src/com/android/bluetooth/sap/SapMessage.java +46 −78 Original line number Diff line number Diff line package com.android.bluetooth.sap; import android.hardware.radio.V1_0.ISap; import android.hardware.radio.V1_0.SapApduType; import android.hardware.radio.V1_0.SapTransferProtocol; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -153,7 +157,7 @@ public class SapMessage { static AtomicInteger sNextSerial = new AtomicInteger(1); // Map<rilSerial, RequestType> - HashTable is synchronized private static Map<Integer, Integer> sOngoingRequests = new Hashtable<Integer, Integer>(); static Map<Integer, Integer> sOngoingRequests = new Hashtable<Integer, Integer>(); private boolean mSendToRil = false; // set to true for messages that needs to go to the RIL private boolean mClearRilQueue = false; /* set to true for messages that needs to cause the sOngoingRequests to be cleared. */ Loading Loading @@ -704,139 +708,103 @@ public class SapMessage { dataLength[3] = (byte)((length) & 0xff); out.writeRawBytes(dataLength); } private ArrayList<Byte> primitiveArrayToContainerArrayList(byte[] arr) { ArrayList<Byte> arrayList = new ArrayList<>(arr.length); for (byte b : arr) { arrayList.add(b); } return arrayList; } /** * Write this SAP message as a rild compatible protobuf message. * Solicited Requests are formed as follows: * int type - the rild-bt type * int serial - an number incrementing for each message. * Send the message by calling corresponding ISap api. */ public void writeReqToStream(CodedOutputStreamMicro out) throws IOException { public void send(ISap sapProxy) throws Exception { int rilSerial = sNextSerial.getAndIncrement(); SapApi.MsgHeader msg = new MsgHeader(); /* Common variables for all requests */ msg.setToken(rilSerial); msg.setType(SapApi.REQUEST); msg.setError(SapApi.RIL_E_UNUSED); Log.e(TAG, "callISapReq: called for mMsgType " + mMsgType + " rilSerial " + rilSerial); /* Update the ongoing requests queue */ if (mClearRilQueue == true) { resetPendingRilMessages(); } // No need to synchronize this, as the HashList is already doing this. sOngoingRequests.put(rilSerial, mMsgType); switch(mMsgType) { case ID_CONNECT_REQ: { SapApi.RIL_SIM_SAP_CONNECT_REQ reqMsg = new RIL_SIM_SAP_CONNECT_REQ(); reqMsg.setMaxMessageSize(mMaxMsgSize); msg.setId(SapApi.RIL_SIM_SAP_CONNECT); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.connectReq(rilSerial, mMaxMsgSize); break; } case ID_DISCONNECT_REQ: { SapApi.RIL_SIM_SAP_DISCONNECT_REQ reqMsg = new RIL_SIM_SAP_DISCONNECT_REQ(); msg.setId(SapApi.RIL_SIM_SAP_DISCONNECT); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.disconnectReq(rilSerial); break; } case ID_TRANSFER_APDU_REQ: { SapApi.RIL_SIM_SAP_APDU_REQ reqMsg = new RIL_SIM_SAP_APDU_REQ(); msg.setId(SapApi.RIL_SIM_SAP_APDU); int type; ArrayList<Byte> command; if(mApdu != null) { reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU); reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu)); type = SapApduType.APDU; command = primitiveArrayToContainerArrayList(mApdu); } else if (mApdu7816 != null) { reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU7816); reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu7816)); type = SapApduType.APDU7816; command = primitiveArrayToContainerArrayList(mApdu7816); } else { Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ"); throw new IllegalArgumentException(); } msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.apduReq(rilSerial, type, command); break; } case ID_SET_TRANSPORT_PROTOCOL_REQ: { SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ reqMsg = new RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ(); msg.setId(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL); int transportProtocol; if(mTransportProtocol == TRANS_PROTO_T0) { reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t0); transportProtocol = SapTransferProtocol.T0; } else if(mTransportProtocol == TRANS_PROTO_T1) { reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t1); transportProtocol = SapTransferProtocol.T1; } else { Log.e(TAG, "Missing or invalid TransportProtocol parameter in"+ " SET_TRANSPORT_PROTOCOL_REQ: "+ mTransportProtocol ); Log.e(TAG, "Missing or invalid TransportProtocol parameter in" + " SET_TRANSPORT_PROTOCOL_REQ: " + mTransportProtocol); throw new IllegalArgumentException(); } msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.setTransferProtocolReq(rilSerial, transportProtocol); break; } case ID_TRANSFER_ATR_REQ: { SapApi.RIL_SIM_SAP_TRANSFER_ATR_REQ reqMsg = new RIL_SIM_SAP_TRANSFER_ATR_REQ(); msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_ATR); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.transferAtrReq(rilSerial); break; } case ID_POWER_SIM_OFF_REQ: { SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ(); msg.setId(SapApi.RIL_SIM_SAP_POWER); reqMsg.setState(false); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.powerReq(rilSerial, false); break; } case ID_POWER_SIM_ON_REQ: { SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ(); msg.setId(SapApi.RIL_SIM_SAP_POWER); reqMsg.setState(true); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.powerReq(rilSerial, true); break; } case ID_RESET_SIM_REQ: { SapApi.RIL_SIM_SAP_RESET_SIM_REQ reqMsg = new RIL_SIM_SAP_RESET_SIM_REQ(); msg.setId(SapApi.RIL_SIM_SAP_RESET_SIM); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.resetSimReq(rilSerial); break; } case ID_TRANSFER_CARD_READER_STATUS_REQ: { SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ reqMsg = new RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ(); msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS); msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray())); writeLength(msg.getSerializedSize(), out); msg.writeTo(out); sapProxy.transferCardReaderStatusReq(rilSerial); break; } default: Log.e(TAG, "Unknown request type"); throw new IllegalArgumentException(); } /* Update the ongoing requests queue */ if(mClearRilQueue == true) { resetPendingRilMessages(); } // No need to synchronize this, as the HashList is already doing this. sOngoingRequests.put(rilSerial, mMsgType); out.flush(); if (VERBOSE) Log.e(TAG, "callISapReq: done without exceptions"); } public static SapMessage newInstance(MsgHeader msg) throws IOException { Loading
android/app/src/com/android/bluetooth/sap/SapRilReceiver.java +165 −0 Original line number Diff line number Diff line Loading @@ -2,12 +2,17 @@ package com.android.bluetooth.sap; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.android.btsap.SapApi.MsgHeader; import com.google.protobuf.micro.CodedInputStreamMicro; import com.google.protobuf.micro.CodedOutputStreamMicro; import android.hardware.radio.V1_0.ISap; import android.hardware.radio.V1_0.ISapCallback; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.Handler; Loading @@ -27,15 +32,175 @@ public class SapRilReceiver implements Runnable { LocalSocket mSocket = null; CodedOutputStreamMicro mRilBtOutStream = null; InputStream mRilBtInStream = null; SapCallback mSapCallback; ISap mSapProxy; private Handler mSapServerMsgHandler = null; private Handler mSapServiceHandler = null; public static final int RIL_MAX_COMMAND_BYTES = (8 * 1024); byte[] buffer = new byte[RIL_MAX_COMMAND_BYTES]; private void sendSapMessage(SapMessage sapMessage) { if (sapMessage.getMsgType() < SapMessage.ID_RIL_BASE) { sendClientMessage(sapMessage); } else { sendRilIndMessage(sapMessage); } } private void removeOngoingReqAndSendMessage(int token, SapMessage sapMessage) { Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "removeOngoingReqAndSendMessage: token " + token + " reqType " + (reqType == null ? "null" : SapMessage.getMsgTypeName(reqType))); } sendSapMessage(sapMessage); } class SapCallback extends ISapCallback.Stub { public void connectResponse(int token, int sapConnectRsp, int maxMsgSize) { Log.d(TAG, "connectResponse: token " + token + " sapConnectRsp " + sapConnectRsp + " maxMsgSize " + maxMsgSize); SapMessage sapMessage = new SapMessage(SapMessage.ID_CONNECT_RESP); sapMessage.setConnectionStatus(sapConnectRsp); if (sapConnectRsp == SapMessage.CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED) { sapMessage.setMaxMsgSize(maxMsgSize); } sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); } public void disconnectResponse(int token) { Log.d(TAG, "disconnectResponse: token " + token); SapMessage sapMessage = new SapMessage(SapMessage.ID_DISCONNECT_RESP); sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); } public void disconnectIndication(int token, int disconnectType) { Log.d(TAG, "disconnectIndication: token " + token + " disconnectType " + disconnectType); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNSOL_DISCONNECT_IND); sapMessage.setDisconnectionType(disconnectType); sendSapMessage(sapMessage); } public void apduResponse(int token, int resultCode, ArrayList<Byte> apduRsp) { Log.d(TAG, "apduResponse: token " + token); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_APDU_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setApduResp(arrayListToPrimitiveArray(apduRsp)); } removeOngoingReqAndSendMessage(token, sapMessage); } public void transferAtrResponse(int token, int resultCode, ArrayList<Byte> atr) { Log.d(TAG, "transferAtrResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_ATR_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setAtr(arrayListToPrimitiveArray(atr)); } removeOngoingReqAndSendMessage(token, sapMessage); } public void powerResponse(int token, int resultCode) { Log.d(TAG, "powerResponse: token " + token + " resultCode " + resultCode); Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "powerResponse: reqType " + (reqType == null ? "null" : SapMessage.getMsgTypeName(reqType))); } SapMessage sapMessage; if (reqType == SapMessage.ID_POWER_SIM_OFF_REQ) { sapMessage = new SapMessage(SapMessage.ID_POWER_SIM_OFF_RESP); } else if (reqType == SapMessage.ID_POWER_SIM_ON_REQ) { sapMessage = new SapMessage(SapMessage.ID_POWER_SIM_ON_RESP); } else { return; } sapMessage.setResultCode(resultCode); sendSapMessage(sapMessage); } public void resetSimResponse(int token, int resultCode) { Log.d(TAG, "resetSimResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_RESET_SIM_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); } public void statusIndication(int token, int status) { Log.d(TAG, "statusIndication: token " + token + " status " + status); SapMessage sapMessage = new SapMessage(SapMessage.ID_STATUS_IND); sapMessage.setStatusChange(status); sendSapMessage(sapMessage); } public void transferCardReaderStatusResponse( int token, int resultCode, int cardReaderStatus) { Log.d(TAG, "transferCardReaderStatusResponse: token " + token + " resultCode " + resultCode + " cardReaderStatus " + cardReaderStatus); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_CARD_READER_STATUS_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { sapMessage.setCardReaderStatus(cardReaderStatus); } removeOngoingReqAndSendMessage(token, sapMessage); } public void errorResponse(int token) { Log.d(TAG, "errorResponse: token " + token); // Since ERROR_RESP isn't supported by createUnsolicited(), keeping behavior same here // SapMessage sapMessage = new SapMessage(SapMessage.ID_ERROR_RESP); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNKNOWN); sendSapMessage(sapMessage); } public void transferProtocolResponse(int token, int resultCode) { Log.d(TAG, "transferProtocolResponse: token " + token + " resultCode " + resultCode); SapMessage sapMessage = new SapMessage(SapMessage.ID_SET_TRANSPORT_PROTOCOL_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); } } public static byte[] arrayListToPrimitiveArray(List<Byte> bytes) { byte[] ret = new byte[bytes.size()]; for (int i = 0; i < ret.length; i++) { ret[i] = bytes.get(i); } return ret; } public ISap getSapProxy() { if (mSapProxy != null) { return mSapProxy; } try { mSapProxy = ISap.getService(SOCKET_NAME_RIL_BT); if (mSapProxy != null) { Log.d(TAG, "getSapProxy: mSapProxy != null; calling setCallback()"); // todo(b/31632518): need to do this again if remote process crashes/restarts mSapProxy.setCallback(mSapCallback); } else { Log.e(TAG, "getSapProxy: mSapProxy == null"); } } catch (Exception e) { Log.e(TAG, "getSapProxy: exception", e); } return mSapProxy; } public SapRilReceiver(Handler SapServerMsgHandler, Handler sapServiceHandler) { mSapServerMsgHandler = SapServerMsgHandler; mSapServiceHandler = sapServiceHandler; mSapCallback = new SapCallback(); mSapProxy = getSapProxy(); } /** Loading
android/app/src/com/android/bluetooth/sap/SapServer.java +20 −14 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.radio.V1_0.ISap; import android.os.Handler; import android.os.Handler.Callback; import android.os.HandlerThread; Loading @@ -20,7 +21,6 @@ import android.telephony.TelephonyManager; import android.util.Log; import com.android.bluetooth.R; import com.google.protobuf.micro.CodedOutputStreamMicro; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; Loading Loading @@ -58,8 +58,6 @@ public class SapServer extends Thread implements Callback { /* RFCOMM socket I/O streams */ private BufferedOutputStream mRfcommOut = null; private BufferedInputStream mRfcommIn = null; /* The RIL output stream - the input stream is owned by the SapRilReceiver object */ private CodedOutputStreamMicro mRilBtOutStream = null; /* References to the SapRilReceiver object */ private SapRilReceiver mRilBtReceiver = null; private Thread mRilBtReceiverThread = null; Loading Loading @@ -313,9 +311,12 @@ public class SapServer extends Thread implements Callback { while (!done) { if(VERBOSE) Log.i(TAG, "Waiting for incomming RFCOMM message..."); int requestType = mRfcommIn.read(); if (VERBOSE) Log.i(TAG, "RFCOMM message read..."); if(requestType == -1) { if (VERBOSE) Log.i(TAG, "requestType == -1"); done = true; // EOF reached } else { if (VERBOSE) Log.i(TAG, "requestType != -1"); SapMessage msg = SapMessage.readMessage(requestType, mRfcommIn); /* notify about an incoming message from the BT Client */ SapService.notifyUpdateWakeLock(mSapServiceHandler); Loading Loading @@ -582,7 +583,6 @@ public class SapServer extends Thread implements Callback { } } /************************************************************************* * SAP Server Message Handler Thread Functions *************************************************************************/ Loading @@ -609,7 +609,6 @@ public class SapServer extends Thread implements Callback { case SAP_MSG_RIL_CONNECT: /* The connection to rild-bt have been established. Store the outStream handle * and send the connect request. */ mRilBtOutStream = mRilBtReceiver.getRilBtOutStream(); if(mTestMode != SapMessage.INVALID_VALUE) { SapMessage rilTestModeReq = new SapMessage(SapMessage.ID_RIL_SIM_ACCESS_TEST_REQ); rilTestModeReq.setTestMode(mTestMode); Loading Loading @@ -845,17 +844,24 @@ public class SapServer extends Thread implements Callback { private void sendRilMessage(SapMessage sapMsg) { if(VERBOSE) Log.i(TAG_HANDLER, "sendRilMessage() - " + SapMessage.getMsgTypeName(sapMsg.getMsgType())); try { if(mRilBtOutStream != null) { sapMsg.writeReqToStream(mRilBtOutStream); } /* Else SAP was enabled on a build that did not support SAP, which we will not * handle. */ } catch (IOException e) { Log.e(TAG_HANDLER, "Unable to send message to RIL", e); Log.d(TAG_HANDLER, "sendRilMessage: calling getSapProxy"); ISap sapProxy = mRilBtReceiver.getSapProxy(); if (sapProxy == null) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); sendClientMessage(errorReply); } catch (IllegalArgumentException e) { Log.e(TAG_HANDLER, "Unable encode message", e); return; } try { sapMsg.send(sapProxy); if (VERBOSE) { Log.d(TAG_HANDLER, "sendRilMessage: sapMsg.callISapReq called " + "successfully"); } } catch (Exception e) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL", e); SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); sendClientMessage(errorReply); } Loading