Loading android/app/src/com/android/bluetooth/sap/SapRilReceiver.java +50 −180 Original line number Diff line number Diff line Loading @@ -22,8 +22,7 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; public class SapRilReceiver implements Runnable { public class SapRilReceiver { private static final String TAG = "SapRilReceiver"; public static final boolean DEBUG = true; public static final boolean VERBOSE = true; Loading @@ -32,12 +31,9 @@ public class SapRilReceiver implements Runnable { // match with constant in ril.cpp - as in RIL.java private static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000; LocalSocket mSocket = null; CodedOutputStreamMicro mRilBtOutStream = null; InputStream mRilBtInStream = null; SapCallback mSapCallback; volatile ISap mSapProxy = null; Object mSapProxyLock = new Object(); final AtomicLong mSapProxyCookie = new AtomicLong(0); final SapProxyDeathRecipient mSapProxyDeathRecipient; Loading Loading @@ -81,6 +77,7 @@ public class SapRilReceiver implements Runnable { public void connectResponse(int token, int sapConnectRsp, int maxMsgSize) { Log.d(TAG, "connectResponse: token " + token + " sapConnectRsp " + sapConnectRsp + " maxMsgSize " + maxMsgSize); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_CONNECT_RESP); sapMessage.setConnectionStatus(sapConnectRsp); if (sapConnectRsp == SapMessage.CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED) { Loading @@ -92,6 +89,7 @@ public class SapRilReceiver implements Runnable { public void disconnectResponse(int token) { Log.d(TAG, "disconnectResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_DISCONNECT_RESP); sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -100,6 +98,7 @@ public class SapRilReceiver implements Runnable { public void disconnectIndication(int token, int disconnectType) { Log.d(TAG, "disconnectIndication: token " + token + " disconnectType " + disconnectType); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNSOL_DISCONNECT_IND); sapMessage.setDisconnectionType(disconnectType); sendSapMessage(sapMessage); Loading @@ -107,6 +106,7 @@ public class SapRilReceiver implements Runnable { public void apduResponse(int token, int resultCode, ArrayList<Byte> apduRsp) { Log.d(TAG, "apduResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_APDU_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -117,6 +117,7 @@ public class SapRilReceiver implements Runnable { public void transferAtrResponse(int token, int resultCode, ArrayList<Byte> atr) { Log.d(TAG, "transferAtrResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_ATR_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -127,6 +128,7 @@ public class SapRilReceiver implements Runnable { public void powerResponse(int token, int resultCode) { Log.d(TAG, "powerResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "powerResponse: reqType " Loading @@ -146,6 +148,7 @@ public class SapRilReceiver implements Runnable { public void resetSimResponse(int token, int resultCode) { Log.d(TAG, "resetSimResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_RESET_SIM_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -153,6 +156,7 @@ public class SapRilReceiver implements Runnable { public void statusIndication(int token, int status) { Log.d(TAG, "statusIndication: token " + token + " status " + status); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_STATUS_IND); sapMessage.setStatusChange(status); sendSapMessage(sapMessage); Loading @@ -162,6 +166,7 @@ public class SapRilReceiver implements Runnable { int token, int resultCode, int cardReaderStatus) { Log.d(TAG, "transferCardReaderStatusResponse: token " + token + " resultCode " + resultCode + " cardReaderStatus " + cardReaderStatus); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_CARD_READER_STATUS_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -172,6 +177,7 @@ public class SapRilReceiver implements Runnable { public void errorResponse(int token) { Log.d(TAG, "errorResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); // 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); Loading @@ -180,6 +186,7 @@ public class SapRilReceiver implements Runnable { public void transferProtocolResponse(int token, int resultCode) { Log.d(TAG, "transferProtocolResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_SET_TRANSPORT_PROTOCOL_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -194,7 +201,12 @@ public class SapRilReceiver implements Runnable { return ret; } public Object getSapProxyLock() { return mSapProxyLock; } public ISap getSapProxy() { synchronized (mSapProxyLock) { if (mSapProxy != null) { return mSapProxy; } Loading @@ -202,135 +214,53 @@ public class SapRilReceiver implements Runnable { try { mSapProxy = ISap.getService(SOCKET_NAME_RIL_BT); if (mSapProxy != null) { Log.d(TAG, "getSapProxy: mSapProxy != null; calling setCallback()"); mSapProxy.linkToDeath(mSapProxyDeathRecipient, mSapProxyCookie.incrementAndGet()); mSapProxy.linkToDeath( mSapProxyDeathRecipient, mSapProxyCookie.incrementAndGet()); mSapProxy.setCallback(mSapCallback); } else { Log.e(TAG, "getSapProxy: mSapProxy == null"); } } catch (RemoteException | RuntimeException e) { mSapProxy = null; Log.e(TAG, "getSapProxy: exception: " + e); } // if service is not up, treat it like death notification to try to get service again if (mSapProxy == null) { // if service is not up, treat it like death notification to try to get service // again mSapServerMsgHandler.sendMessageDelayed( mSapServerMsgHandler.obtainMessage( SapServer.SAP_PROXY_DEAD, mSapProxyCookie.get()), SapServer.ISAP_GET_SERVICE_DELAY_MILLIS); Log.e(TAG, "getSapProxy: exception", e); } return mSapProxy; } } public void resetSapProxy() { synchronized (mSapProxyLock) { mSapProxy = null; } } public SapRilReceiver(Handler SapServerMsgHandler, Handler sapServiceHandler) { mSapServerMsgHandler = SapServerMsgHandler; mSapServiceHandler = sapServiceHandler; mSapCallback = new SapCallback(); mSapProxyDeathRecipient = new SapProxyDeathRecipient(); synchronized (mSapProxyLock) { mSapProxy = getSapProxy(); } /** * Open the RIL-BT socket in rild. Will continuously try to open the BT socket until * success. (Based on the approach used to open the rild socket in telephony) * @return The socket handle */ public static LocalSocket openRilBtSocket() { int retryCount = 0; LocalSocket rilSocket = null; for (;;) { LocalSocketAddress address; try { rilSocket = new LocalSocket(); address = new LocalSocketAddress(SOCKET_NAME_RIL_BT, LocalSocketAddress.Namespace.RESERVED); rilSocket.connect(address); break; // Socket opened } catch (IOException ex){ try { if (rilSocket != null) { rilSocket.close(); } } catch (IOException ex2) { //ignore failure to close after failure to connect } // don't print an error message after the the first time // or after the 8th time if (retryCount == 8) { Log.e (TAG, "Couldn't find '" + SOCKET_NAME_RIL_BT + "' socket after " + retryCount + " times, continuing to retry silently"); } else if (retryCount > 0 && retryCount < 8) { Log.i (TAG, "Couldn't find '" + SOCKET_NAME_RIL_BT + "' socket; retrying after timeout"); if (VERBOSE) Log.w(TAG, ex); } try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } retryCount++; continue; } } return rilSocket; } public CodedOutputStreamMicro getRilBtOutStream() { return mRilBtOutStream; } /** * Notify SapServer that this class is ready for shutdown. */ private void notifyShutdown() { void notifyShutdown() { if (DEBUG) Log.i(TAG, "notifyShutdown()"); // If we are already shutdown, don't bother sending a notification. synchronized (this) { if (mSocket != null) sendShutdownMessage(); } } /** * This will terminate the SapRilReceiver thread, by closing the RIL-BT in-/output * streams. */ public void shutdown() { if (DEBUG) Log.i(TAG, "shutdown()"); /* On Android you need to close the IOstreams using Socket.shutdown* * The IOstream close must not be used, as it some how decouples the * stream from the socket, and when the socket is closed, the pending * reads never return nor throw and exception. * Hence here we use the shutdown method: */ synchronized (this) { if (mSocket != null) { try { mSocket.shutdownOutput(); } catch (IOException e) {} try { mSocket.shutdownInput(); } catch (IOException e) {} try { mSocket.close(); } catch (IOException ex) { if (VERBOSE) Log.e(TAG,"Uncaught exception", ex); } finally { mSocket = null; } } synchronized (mSapProxyLock) { if (mSapProxy != null) sendShutdownMessage(); } } Loading Loading @@ -386,70 +316,10 @@ public class SapRilReceiver implements Runnable { return messageLength; } /** * The RIL reader thread. Will handle open of the RIL-BT socket, and notify * SapServer when done. */ @Override public void run() { try { if (VERBOSE) Log.i(TAG, "Starting RilBtReceiverThread..."); mSocket = openRilBtSocket(); mRilBtInStream = mSocket.getInputStream(); mRilBtOutStream = CodedOutputStreamMicro.newInstance(mSocket.getOutputStream()); // Notify the SapServer that we have connected to the RilBtSocket sendRilConnectMessage(); // The main loop - read messages and forward to SAP server for (;;) { SapMessage sapMsg = null; MsgHeader rilMsg; if (VERBOSE) Log.i(TAG, "Waiting for incoming message..."); int length = readMessage(mRilBtInStream, buffer); SapService.notifyUpdateWakeLock(mSapServiceHandler); if (length == -1) { if (DEBUG) Log.i(TAG, "EOF reached - closing down."); break; } CodedInputStreamMicro msgStream = CodedInputStreamMicro.newInstance(buffer, 0, length); rilMsg = MsgHeader.parseFrom(msgStream); if (VERBOSE) Log.i(TAG, "Message received."); sapMsg = SapMessage.newInstance(rilMsg); if (sapMsg != null && sapMsg.getMsgType() != SapMessage.INVALID_VALUE) { if (sapMsg.getMsgType() < SapMessage.ID_RIL_BASE) { sendClientMessage(sapMsg); } else { sendRilIndMessage(sapMsg); } } // else simply ignore it } } catch (IOException e) { notifyShutdown(); /* Only needed in case of a connection error */ Log.i(TAG, "'" + SOCKET_NAME_RIL_BT + "' socket inputStream closed", e); } finally { Log.i(TAG, "Disconnected from '" + SOCKET_NAME_RIL_BT + "' socket"); } } /** * Notify SapServer that the RIL socket is connected */ private void sendRilConnectMessage() { void sendRilConnectMessage() { if (mSapServerMsgHandler != null) { mSapServerMsgHandler.sendEmptyMessage(SapServer.SAP_MSG_RIL_CONNECT); } Loading android/app/src/com/android/bluetooth/sap/SapServer.java +29 −30 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ public class SapServer extends Thread implements Callback { private BufferedInputStream mRfcommIn = null; /* References to the SapRilReceiver object */ private SapRilReceiver mRilBtReceiver = null; private Thread mRilBtReceiverThread = null; /* The message handler members */ private Handler mSapHandler = null; private HandlerThread mHandlerThread = null; Loading Loading @@ -309,7 +308,6 @@ public class SapServer extends Thread implements Callback { mSapHandler = new Handler(sapLooper, this); mRilBtReceiver = new SapRilReceiver(mSapHandler, mSapServiceHandler); mRilBtReceiverThread = new Thread(mRilBtReceiver, "RilBtReceiver"); boolean done = false; while (!done) { if(VERBOSE) Log.i(TAG, "Waiting for incomming RFCOMM message..."); Loading Loading @@ -452,14 +450,10 @@ public class SapServer extends Thread implements Callback { mHandlerThread.join(); mHandlerThread = null; } catch (InterruptedException e) {} if(mRilBtReceiverThread != null) try { if (mRilBtReceiver != null) { mRilBtReceiver.shutdown(); mRilBtReceiver.resetSapProxy(); mRilBtReceiver = null; } mRilBtReceiverThread.join(); mRilBtReceiverThread = null; } catch (InterruptedException e) {} if(mRfcommIn != null) try { if(VERBOSE) Log.i(TAG, "Closing mRfcommIn..."); Loading Loading @@ -521,9 +515,9 @@ public class SapServer extends Thread implements Callback { * 2) Send a RIL_SIM_SAP_CONNECT request to RILD * 3) Send a RIL_SIM_RESET request and a connect confirm to the SAP client */ changeState(SAP_STATE.CONNECTING); if(mRilBtReceiverThread != null) { // Open the RIL socket, and wait for the complete message: SAP_MSG_RIL_CONNECT mRilBtReceiverThread.start(); if (mRilBtReceiver != null) { // Notify the SapServer that we have connected to the SAP service mRilBtReceiver.sendRilConnectMessage(); // Don't send reply yet reply = null; } else { Loading Loading @@ -640,6 +634,7 @@ public class SapServer extends Thread implements Callback { break; case SAP_PROXY_DEAD: if ((long) msg.obj == mRilBtReceiver.mSapProxyCookie.get()) { mRilBtReceiver.notifyShutdown(); /* Only needed in case of a connection error */ mRilBtReceiver.resetSapProxy(); // todo: rild should be back up since message was sent with a delay. this is a hack. Loading Loading @@ -856,9 +851,11 @@ public class SapServer extends Thread implements Callback { + SapMessage.getMsgTypeName(sapMsg.getMsgType())); Log.d(TAG_HANDLER, "sendRilMessage: calling getSapProxy"); synchronized (mRilBtReceiver.getSapProxyLock()) { ISap sapProxy = mRilBtReceiver.getSapProxy(); if (sapProxy == null) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); return; } Loading @@ -872,11 +869,13 @@ public class SapServer extends Thread implements Callback { Log.e(TAG_HANDLER, "sendRilMessage: IllegalArgumentException", e); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); } catch (RemoteException | RuntimeException e) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL", e); Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL: " + e); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); mRilBtReceiver.notifyShutdown(); /* Only needed in case of a connection error */ mRilBtReceiver.resetSapProxy(); } } } /** * Only call this from the sapHandler thread. Loading Loading
android/app/src/com/android/bluetooth/sap/SapRilReceiver.java +50 −180 Original line number Diff line number Diff line Loading @@ -22,8 +22,7 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; public class SapRilReceiver implements Runnable { public class SapRilReceiver { private static final String TAG = "SapRilReceiver"; public static final boolean DEBUG = true; public static final boolean VERBOSE = true; Loading @@ -32,12 +31,9 @@ public class SapRilReceiver implements Runnable { // match with constant in ril.cpp - as in RIL.java private static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000; LocalSocket mSocket = null; CodedOutputStreamMicro mRilBtOutStream = null; InputStream mRilBtInStream = null; SapCallback mSapCallback; volatile ISap mSapProxy = null; Object mSapProxyLock = new Object(); final AtomicLong mSapProxyCookie = new AtomicLong(0); final SapProxyDeathRecipient mSapProxyDeathRecipient; Loading Loading @@ -81,6 +77,7 @@ public class SapRilReceiver implements Runnable { public void connectResponse(int token, int sapConnectRsp, int maxMsgSize) { Log.d(TAG, "connectResponse: token " + token + " sapConnectRsp " + sapConnectRsp + " maxMsgSize " + maxMsgSize); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_CONNECT_RESP); sapMessage.setConnectionStatus(sapConnectRsp); if (sapConnectRsp == SapMessage.CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED) { Loading @@ -92,6 +89,7 @@ public class SapRilReceiver implements Runnable { public void disconnectResponse(int token) { Log.d(TAG, "disconnectResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_DISCONNECT_RESP); sapMessage.setResultCode(SapMessage.INVALID_VALUE); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -100,6 +98,7 @@ public class SapRilReceiver implements Runnable { public void disconnectIndication(int token, int disconnectType) { Log.d(TAG, "disconnectIndication: token " + token + " disconnectType " + disconnectType); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_RIL_UNSOL_DISCONNECT_IND); sapMessage.setDisconnectionType(disconnectType); sendSapMessage(sapMessage); Loading @@ -107,6 +106,7 @@ public class SapRilReceiver implements Runnable { public void apduResponse(int token, int resultCode, ArrayList<Byte> apduRsp) { Log.d(TAG, "apduResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_APDU_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -117,6 +117,7 @@ public class SapRilReceiver implements Runnable { public void transferAtrResponse(int token, int resultCode, ArrayList<Byte> atr) { Log.d(TAG, "transferAtrResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_ATR_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -127,6 +128,7 @@ public class SapRilReceiver implements Runnable { public void powerResponse(int token, int resultCode) { Log.d(TAG, "powerResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); Integer reqType = SapMessage.sOngoingRequests.remove(token); if (VERBOSE) { Log.d(TAG, "powerResponse: reqType " Loading @@ -146,6 +148,7 @@ public class SapRilReceiver implements Runnable { public void resetSimResponse(int token, int resultCode) { Log.d(TAG, "resetSimResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_RESET_SIM_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -153,6 +156,7 @@ public class SapRilReceiver implements Runnable { public void statusIndication(int token, int status) { Log.d(TAG, "statusIndication: token " + token + " status " + status); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_STATUS_IND); sapMessage.setStatusChange(status); sendSapMessage(sapMessage); Loading @@ -162,6 +166,7 @@ public class SapRilReceiver implements Runnable { int token, int resultCode, int cardReaderStatus) { Log.d(TAG, "transferCardReaderStatusResponse: token " + token + " resultCode " + resultCode + " cardReaderStatus " + cardReaderStatus); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_TRANSFER_CARD_READER_STATUS_RESP); sapMessage.setResultCode(resultCode); if (resultCode == SapMessage.RESULT_OK) { Loading @@ -172,6 +177,7 @@ public class SapRilReceiver implements Runnable { public void errorResponse(int token) { Log.d(TAG, "errorResponse: token " + token); SapService.notifyUpdateWakeLock(mSapServiceHandler); // 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); Loading @@ -180,6 +186,7 @@ public class SapRilReceiver implements Runnable { public void transferProtocolResponse(int token, int resultCode) { Log.d(TAG, "transferProtocolResponse: token " + token + " resultCode " + resultCode); SapService.notifyUpdateWakeLock(mSapServiceHandler); SapMessage sapMessage = new SapMessage(SapMessage.ID_SET_TRANSPORT_PROTOCOL_RESP); sapMessage.setResultCode(resultCode); removeOngoingReqAndSendMessage(token, sapMessage); Loading @@ -194,7 +201,12 @@ public class SapRilReceiver implements Runnable { return ret; } public Object getSapProxyLock() { return mSapProxyLock; } public ISap getSapProxy() { synchronized (mSapProxyLock) { if (mSapProxy != null) { return mSapProxy; } Loading @@ -202,135 +214,53 @@ public class SapRilReceiver implements Runnable { try { mSapProxy = ISap.getService(SOCKET_NAME_RIL_BT); if (mSapProxy != null) { Log.d(TAG, "getSapProxy: mSapProxy != null; calling setCallback()"); mSapProxy.linkToDeath(mSapProxyDeathRecipient, mSapProxyCookie.incrementAndGet()); mSapProxy.linkToDeath( mSapProxyDeathRecipient, mSapProxyCookie.incrementAndGet()); mSapProxy.setCallback(mSapCallback); } else { Log.e(TAG, "getSapProxy: mSapProxy == null"); } } catch (RemoteException | RuntimeException e) { mSapProxy = null; Log.e(TAG, "getSapProxy: exception: " + e); } // if service is not up, treat it like death notification to try to get service again if (mSapProxy == null) { // if service is not up, treat it like death notification to try to get service // again mSapServerMsgHandler.sendMessageDelayed( mSapServerMsgHandler.obtainMessage( SapServer.SAP_PROXY_DEAD, mSapProxyCookie.get()), SapServer.ISAP_GET_SERVICE_DELAY_MILLIS); Log.e(TAG, "getSapProxy: exception", e); } return mSapProxy; } } public void resetSapProxy() { synchronized (mSapProxyLock) { mSapProxy = null; } } public SapRilReceiver(Handler SapServerMsgHandler, Handler sapServiceHandler) { mSapServerMsgHandler = SapServerMsgHandler; mSapServiceHandler = sapServiceHandler; mSapCallback = new SapCallback(); mSapProxyDeathRecipient = new SapProxyDeathRecipient(); synchronized (mSapProxyLock) { mSapProxy = getSapProxy(); } /** * Open the RIL-BT socket in rild. Will continuously try to open the BT socket until * success. (Based on the approach used to open the rild socket in telephony) * @return The socket handle */ public static LocalSocket openRilBtSocket() { int retryCount = 0; LocalSocket rilSocket = null; for (;;) { LocalSocketAddress address; try { rilSocket = new LocalSocket(); address = new LocalSocketAddress(SOCKET_NAME_RIL_BT, LocalSocketAddress.Namespace.RESERVED); rilSocket.connect(address); break; // Socket opened } catch (IOException ex){ try { if (rilSocket != null) { rilSocket.close(); } } catch (IOException ex2) { //ignore failure to close after failure to connect } // don't print an error message after the the first time // or after the 8th time if (retryCount == 8) { Log.e (TAG, "Couldn't find '" + SOCKET_NAME_RIL_BT + "' socket after " + retryCount + " times, continuing to retry silently"); } else if (retryCount > 0 && retryCount < 8) { Log.i (TAG, "Couldn't find '" + SOCKET_NAME_RIL_BT + "' socket; retrying after timeout"); if (VERBOSE) Log.w(TAG, ex); } try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } retryCount++; continue; } } return rilSocket; } public CodedOutputStreamMicro getRilBtOutStream() { return mRilBtOutStream; } /** * Notify SapServer that this class is ready for shutdown. */ private void notifyShutdown() { void notifyShutdown() { if (DEBUG) Log.i(TAG, "notifyShutdown()"); // If we are already shutdown, don't bother sending a notification. synchronized (this) { if (mSocket != null) sendShutdownMessage(); } } /** * This will terminate the SapRilReceiver thread, by closing the RIL-BT in-/output * streams. */ public void shutdown() { if (DEBUG) Log.i(TAG, "shutdown()"); /* On Android you need to close the IOstreams using Socket.shutdown* * The IOstream close must not be used, as it some how decouples the * stream from the socket, and when the socket is closed, the pending * reads never return nor throw and exception. * Hence here we use the shutdown method: */ synchronized (this) { if (mSocket != null) { try { mSocket.shutdownOutput(); } catch (IOException e) {} try { mSocket.shutdownInput(); } catch (IOException e) {} try { mSocket.close(); } catch (IOException ex) { if (VERBOSE) Log.e(TAG,"Uncaught exception", ex); } finally { mSocket = null; } } synchronized (mSapProxyLock) { if (mSapProxy != null) sendShutdownMessage(); } } Loading Loading @@ -386,70 +316,10 @@ public class SapRilReceiver implements Runnable { return messageLength; } /** * The RIL reader thread. Will handle open of the RIL-BT socket, and notify * SapServer when done. */ @Override public void run() { try { if (VERBOSE) Log.i(TAG, "Starting RilBtReceiverThread..."); mSocket = openRilBtSocket(); mRilBtInStream = mSocket.getInputStream(); mRilBtOutStream = CodedOutputStreamMicro.newInstance(mSocket.getOutputStream()); // Notify the SapServer that we have connected to the RilBtSocket sendRilConnectMessage(); // The main loop - read messages and forward to SAP server for (;;) { SapMessage sapMsg = null; MsgHeader rilMsg; if (VERBOSE) Log.i(TAG, "Waiting for incoming message..."); int length = readMessage(mRilBtInStream, buffer); SapService.notifyUpdateWakeLock(mSapServiceHandler); if (length == -1) { if (DEBUG) Log.i(TAG, "EOF reached - closing down."); break; } CodedInputStreamMicro msgStream = CodedInputStreamMicro.newInstance(buffer, 0, length); rilMsg = MsgHeader.parseFrom(msgStream); if (VERBOSE) Log.i(TAG, "Message received."); sapMsg = SapMessage.newInstance(rilMsg); if (sapMsg != null && sapMsg.getMsgType() != SapMessage.INVALID_VALUE) { if (sapMsg.getMsgType() < SapMessage.ID_RIL_BASE) { sendClientMessage(sapMsg); } else { sendRilIndMessage(sapMsg); } } // else simply ignore it } } catch (IOException e) { notifyShutdown(); /* Only needed in case of a connection error */ Log.i(TAG, "'" + SOCKET_NAME_RIL_BT + "' socket inputStream closed", e); } finally { Log.i(TAG, "Disconnected from '" + SOCKET_NAME_RIL_BT + "' socket"); } } /** * Notify SapServer that the RIL socket is connected */ private void sendRilConnectMessage() { void sendRilConnectMessage() { if (mSapServerMsgHandler != null) { mSapServerMsgHandler.sendEmptyMessage(SapServer.SAP_MSG_RIL_CONNECT); } Loading
android/app/src/com/android/bluetooth/sap/SapServer.java +29 −30 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ public class SapServer extends Thread implements Callback { private BufferedInputStream mRfcommIn = null; /* References to the SapRilReceiver object */ private SapRilReceiver mRilBtReceiver = null; private Thread mRilBtReceiverThread = null; /* The message handler members */ private Handler mSapHandler = null; private HandlerThread mHandlerThread = null; Loading Loading @@ -309,7 +308,6 @@ public class SapServer extends Thread implements Callback { mSapHandler = new Handler(sapLooper, this); mRilBtReceiver = new SapRilReceiver(mSapHandler, mSapServiceHandler); mRilBtReceiverThread = new Thread(mRilBtReceiver, "RilBtReceiver"); boolean done = false; while (!done) { if(VERBOSE) Log.i(TAG, "Waiting for incomming RFCOMM message..."); Loading Loading @@ -452,14 +450,10 @@ public class SapServer extends Thread implements Callback { mHandlerThread.join(); mHandlerThread = null; } catch (InterruptedException e) {} if(mRilBtReceiverThread != null) try { if (mRilBtReceiver != null) { mRilBtReceiver.shutdown(); mRilBtReceiver.resetSapProxy(); mRilBtReceiver = null; } mRilBtReceiverThread.join(); mRilBtReceiverThread = null; } catch (InterruptedException e) {} if(mRfcommIn != null) try { if(VERBOSE) Log.i(TAG, "Closing mRfcommIn..."); Loading Loading @@ -521,9 +515,9 @@ public class SapServer extends Thread implements Callback { * 2) Send a RIL_SIM_SAP_CONNECT request to RILD * 3) Send a RIL_SIM_RESET request and a connect confirm to the SAP client */ changeState(SAP_STATE.CONNECTING); if(mRilBtReceiverThread != null) { // Open the RIL socket, and wait for the complete message: SAP_MSG_RIL_CONNECT mRilBtReceiverThread.start(); if (mRilBtReceiver != null) { // Notify the SapServer that we have connected to the SAP service mRilBtReceiver.sendRilConnectMessage(); // Don't send reply yet reply = null; } else { Loading Loading @@ -640,6 +634,7 @@ public class SapServer extends Thread implements Callback { break; case SAP_PROXY_DEAD: if ((long) msg.obj == mRilBtReceiver.mSapProxyCookie.get()) { mRilBtReceiver.notifyShutdown(); /* Only needed in case of a connection error */ mRilBtReceiver.resetSapProxy(); // todo: rild should be back up since message was sent with a delay. this is a hack. Loading Loading @@ -856,9 +851,11 @@ public class SapServer extends Thread implements Callback { + SapMessage.getMsgTypeName(sapMsg.getMsgType())); Log.d(TAG_HANDLER, "sendRilMessage: calling getSapProxy"); synchronized (mRilBtReceiver.getSapProxyLock()) { ISap sapProxy = mRilBtReceiver.getSapProxy(); if (sapProxy == null) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL; sapProxy is null"); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); return; } Loading @@ -872,11 +869,13 @@ public class SapServer extends Thread implements Callback { Log.e(TAG_HANDLER, "sendRilMessage: IllegalArgumentException", e); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); } catch (RemoteException | RuntimeException e) { Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL", e); Log.e(TAG_HANDLER, "sendRilMessage: Unable to send message to RIL: " + e); sendClientMessage(new SapMessage(SapMessage.ID_ERROR_RESP)); mRilBtReceiver.notifyShutdown(); /* Only needed in case of a connection error */ mRilBtReceiver.resetSapProxy(); } } } /** * Only call this from the sapHandler thread. Loading