Skip to content
Snippets Groups Projects
Commit 4ed762bd authored by Hyundo Moon's avatar Hyundo Moon Committed by Gerrit Code Review
Browse files

Merge "Add SapRilReceiverTest"

parents 958483f5 f3a3b87f
No related branches found
No related tags found
No related merge requests found
......@@ -279,60 +279,6 @@ public class SapRilReceiver {
}
}
/**
* Read the message into buffer
* @param is
* @param buffer
* @return the length of the message
* @throws IOException
*/
private static int readMessage(InputStream is, byte[] buffer) throws IOException {
int countRead;
int offset;
int remaining;
int messageLength;
// Read in the length of the message
offset = 0;
remaining = 4;
do {
countRead = is.read(buffer, offset, remaining);
if (countRead < 0) {
Log.e(TAG, "Hit EOS reading message length");
return -1;
}
offset += countRead;
remaining -= countRead;
} while (remaining > 0);
messageLength =
((buffer[0] & 0xff) << 24) | ((buffer[1] & 0xff) << 16) | ((buffer[2] & 0xff) << 8)
| (buffer[3] & 0xff);
if (VERBOSE) {
Log.e(TAG, "Message length found to be: " + messageLength);
}
// Read the message
offset = 0;
remaining = messageLength;
do {
countRead = is.read(buffer, offset, remaining);
if (countRead < 0) {
Log.e(TAG,
"Hit EOS reading message. messageLength=" + messageLength + " remaining="
+ remaining);
return -1;
}
offset += countRead;
remaining -= countRead;
} while (remaining > 0);
return messageLength;
}
/**
* Notify SapServer that the RIL socket is connected
*/
......
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.bluetooth.sap;
import static com.android.bluetooth.sap.SapMessage.CON_STATUS_OK;
import static com.android.bluetooth.sap.SapMessage.DISC_GRACEFULL;
import static com.android.bluetooth.sap.SapMessage.ID_CONNECT_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_DISCONNECT_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_POWER_SIM_OFF_REQ;
import static com.android.bluetooth.sap.SapMessage.ID_POWER_SIM_OFF_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_POWER_SIM_ON_REQ;
import static com.android.bluetooth.sap.SapMessage.ID_POWER_SIM_ON_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_RESET_SIM_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_RIL_UNKNOWN;
import static com.android.bluetooth.sap.SapMessage.ID_RIL_UNSOL_DISCONNECT_IND;
import static com.android.bluetooth.sap.SapMessage.ID_SET_TRANSPORT_PROTOCOL_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_STATUS_IND;
import static com.android.bluetooth.sap.SapMessage.ID_TRANSFER_APDU_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_TRANSFER_ATR_RESP;
import static com.android.bluetooth.sap.SapMessage.ID_TRANSFER_CARD_READER_STATUS_RESP;
import static com.android.bluetooth.sap.SapMessage.RESULT_OK;
import static com.android.bluetooth.sap.SapMessage.STATUS_CARD_INSERTED;
import static com.android.bluetooth.sap.SapServer.ISAP_GET_SERVICE_DELAY_MILLIS;
import static com.android.bluetooth.sap.SapServer.SAP_MSG_RFC_REPLY;
import static com.android.bluetooth.sap.SapServer.SAP_MSG_RIL_CONNECT;
import static com.android.bluetooth.sap.SapServer.SAP_MSG_RIL_IND;
import static com.android.bluetooth.sap.SapServer.SAP_PROXY_DEAD;
import static com.android.bluetooth.sap.SapServer.SAP_RIL_SOCK_CLOSED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.hardware.radio.V1_0.ISap;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.util.ArrayList;
import java.util.Arrays;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class SapRilReceiverTest {
private static final long TIMEOUT_MS = 1_000;
private HandlerThread mHandlerThread;
private Handler mServerMsgHandler;
@Spy
private TestHandlerCallback mCallback = new TestHandlerCallback();
@Mock
private Handler mServiceHandler;
@Mock
private ISap mSapProxy;
private SapRilReceiver mReceiver;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mHandlerThread = new HandlerThread("SapRilReceiverTest");
mHandlerThread.start();
mServerMsgHandler = new Handler(mHandlerThread.getLooper(), mCallback);
mReceiver = new SapRilReceiver(mServerMsgHandler, mServiceHandler);
mReceiver.mSapProxy = mSapProxy;
}
@After
public void tearDown() {
mHandlerThread.quit();
}
@Test
public void getSapProxyLock() {
assertThat(mReceiver.getSapProxyLock()).isNotNull();
}
@Test
public void resetSapProxy() throws Exception {
mReceiver.resetSapProxy();
assertThat(mReceiver.mSapProxy).isNull();
verify(mSapProxy).unlinkToDeath(any());
}
@Test
public void notifyShutdown() throws Exception {
mReceiver.notifyShutdown();
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_RIL_SOCK_CLOSED), any());
}
@Test
public void sendRilConnectMessage() throws Exception {
mReceiver.sendRilConnectMessage();
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RIL_CONNECT), any());
}
@Test
public void serviceDied() throws Exception {
long cookie = 1;
mReceiver.mSapProxyDeathRecipient.serviceDied(cookie);
verify(mCallback, timeout(ISAP_GET_SERVICE_DELAY_MILLIS + TIMEOUT_MS))
.receiveMessage(eq(SAP_PROXY_DEAD), argThat(
arg -> (arg instanceof Long) && ((Long) arg == cookie)
));
}
@Test
public void callback_connectResponse() throws Exception {
int token = 1;
int sapConnectRsp = CON_STATUS_OK;
int maxMsgSize = 512;
mReceiver.mSapCallback.connectResponse(token, sapConnectRsp, maxMsgSize);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_CONNECT_RESP
&& sapMsg.getConnectionStatus() == sapConnectRsp;
}
}
));
}
@Test
public void callback_disconnectResponse() throws Exception {
int token = 1;
mReceiver.mSapCallback.disconnectResponse(token);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_DISCONNECT_RESP;
}
}
));
}
@Test
public void callback_disconnectIndication() throws Exception {
int token = 1;
int disconnectType = DISC_GRACEFULL;
mReceiver.mSapCallback.disconnectIndication(token, disconnectType);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RIL_IND), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_RIL_UNSOL_DISCONNECT_IND
&& sapMsg.getDisconnectionType() == disconnectType;
}
}
));
}
@Test
public void callback_apduResponse() throws Exception {
int token = 1;
int resultCode = RESULT_OK;
byte[] apduRsp = new byte[]{0x03, 0x04};
ArrayList<Byte> apduRspList = new ArrayList<>();
for (byte b : apduRsp) {
apduRspList.add(b);
}
mReceiver.mSapCallback.apduResponse(token, resultCode, apduRspList);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_TRANSFER_APDU_RESP
&& sapMsg.getResultCode() == resultCode
&& Arrays.equals(sapMsg.getApduResp(), apduRsp);
}
}
));
}
@Test
public void callback_transferAtrResponse() throws Exception {
int token = 1;
int resultCode = RESULT_OK;
byte[] atr = new byte[]{0x03, 0x04};
ArrayList<Byte> atrList = new ArrayList<>();
for (byte b : atr) {
atrList.add(b);
}
mReceiver.mSapCallback.transferAtrResponse(token, resultCode, atrList);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_TRANSFER_ATR_RESP
&& sapMsg.getResultCode() == resultCode
&& Arrays.equals(sapMsg.getAtr(), atr);
}
}
));
}
@Test
public void callback_powerResponse_powerOff() throws Exception {
int token = 1;
int reqType = ID_POWER_SIM_OFF_REQ;
int resultCode = RESULT_OK;
SapMessage.sOngoingRequests.clear();
SapMessage.sOngoingRequests.put(token, reqType);
mReceiver.mSapCallback.powerResponse(token, resultCode);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_POWER_SIM_OFF_RESP
&& sapMsg.getResultCode() == resultCode;
}
}
));
}
@Test
public void callback_powerResponse_powerOn() throws Exception {
int token = 1;
int reqType = ID_POWER_SIM_ON_REQ;
int resultCode = RESULT_OK;
SapMessage.sOngoingRequests.clear();
SapMessage.sOngoingRequests.put(token, reqType);
mReceiver.mSapCallback.powerResponse(token, resultCode);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_POWER_SIM_ON_RESP
&& sapMsg.getResultCode() == resultCode;
}
}
));
}
@Test
public void callback_resetSimResponse() throws Exception {
int token = 1;
int resultCode = RESULT_OK;
mReceiver.mSapCallback.resetSimResponse(token, resultCode);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_RESET_SIM_RESP
&& sapMsg.getResultCode() == resultCode;
}
}
));
}
@Test
public void callback_statusIndication() throws Exception {
int token = 1;
int statusChange = 2;
mReceiver.mSapCallback.statusIndication(token, statusChange);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_STATUS_IND
&& sapMsg.getStatusChange() == statusChange;
}
}
));
}
@Test
public void callback_transferCardReaderStatusResponse() throws Exception {
int token = 1;
int resultCode = RESULT_OK;
int cardReaderStatus = STATUS_CARD_INSERTED;
mReceiver.mSapCallback.transferCardReaderStatusResponse(
token, resultCode, cardReaderStatus);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_TRANSFER_CARD_READER_STATUS_RESP
&& sapMsg.getResultCode() == resultCode;
}
}
));
}
@Test
public void callback_errorResponse() throws Exception {
int token = 1;
mReceiver.mSapCallback.errorResponse(token);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RIL_IND), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_RIL_UNKNOWN;
}
}
));
}
@Test
public void callback_transferProtocolResponse() throws Exception {
int token = 1;
int resultCode = RESULT_OK;
mReceiver.mSapCallback.transferProtocolResponse(token, resultCode);
verify(mCallback, timeout(TIMEOUT_MS)).receiveMessage(eq(SAP_MSG_RFC_REPLY), argThat(
new ArgumentMatcher<Object>() {
@Override
public boolean matches(Object arg) {
if (!(arg instanceof SapMessage)) {
return false;
}
SapMessage sapMsg = (SapMessage) arg;
return sapMsg.getMsgType() == ID_SET_TRANSPORT_PROTOCOL_RESP
&& sapMsg.getResultCode() == resultCode;
}
}
));
}
public static class TestHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
receiveMessage(msg.what, msg.obj);
return true;
}
public void receiveMessage(int what, Object obj) {}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment