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

Commit 345299ee authored by Amit Mahajan's avatar Amit Mahajan Committed by android-build-merger
Browse files

Merge "Client changes for BT SAP hidl." am: 8388ffbf

am: e3318e30

Change-Id: Iad9703807e0f11e400ccfa74e815aeea4b10cdff
parents e37df32e e3318e30
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);
        }