Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d272c8a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Client changes for BT SAP hidl."

parents df122ffd 3b8e3a16
Loading
Loading
Loading
Loading
+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;
@@ -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. */
@@ -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 {
+165 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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();
    }

    /**
+20 −14
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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);
@@ -582,7 +583,6 @@ public class SapServer extends Thread implements Callback {
        }
    }


    /*************************************************************************
     * SAP Server Message Handler Thread Functions
     *************************************************************************/
@@ -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);
@@ -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);
        }