summaryrefslogtreecommitdiff
path: root/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java')
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java202
1 files changed, 184 insertions, 18 deletions
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
index 384499228..dc8c0e191 100644
--- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
+++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
@@ -5,10 +5,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
+import java.io.PipedOutputStream;
import java.util.concurrent.CopyOnWriteArrayList;
import android.annotation.SuppressLint;
+import android.content.ComponentName;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
@@ -18,17 +19,20 @@ import com.smartdevicelink.exception.SdlException;
import com.smartdevicelink.protocol.AbstractProtocol;
import com.smartdevicelink.protocol.IProtocolListener;
import com.smartdevicelink.protocol.ProtocolMessage;
+import com.smartdevicelink.protocol.SdlPacket;
import com.smartdevicelink.protocol.WiProProtocol;
import com.smartdevicelink.protocol.enums.SessionType;
import com.smartdevicelink.proxy.RPCRequest;
import com.smartdevicelink.streaming.IStreamListener;
import com.smartdevicelink.streaming.StreamPacketizer;
-import com.smartdevicelink.streaming.StreamRPCPacketizer;
+import com.smartdevicelink.streaming.StreamRPCPacketizer;
import com.smartdevicelink.transport.*;
import com.smartdevicelink.transport.enums.TransportType;
public class SdlConnection implements IProtocolListener, ITransportListener, IStreamListener {
+ private static final String TAG = "SdlConnection";
+
SdlTransport _transport = null;
AbstractProtocol _protocol = null;
ISdlConnectionListener _connectionListener = null;
@@ -39,12 +43,14 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
SdlEncoder mSdlEncoder = null;
// Thread safety locks
- Object TRANSPORT_REFERENCE_LOCK = new Object();
+ static Object TRANSPORT_REFERENCE_LOCK = new Object();
Object PROTOCOL_REFERENCE_LOCK = new Object();
-
+
+ private Object SESSION_LOCK = new Object();
private CopyOnWriteArrayList<SdlSession> listenerList = new CopyOnWriteArrayList<SdlSession>();
-
+ private static TransportType legacyTransportRequest = null;
private final static int BUFF_READ_SIZE = 1000000;
+ protected static MultiplexTransportConfig cachedMultiConfig = null;
/**
* Constructor.
@@ -53,6 +59,25 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
* @param transportConfig Transport configuration for this connection.
*/
public SdlConnection(BaseTransportConfig transportConfig) {
+ RouterServiceValidator vlad = null;
+ //Let's check if we can even do multiplexing
+ if(transportConfig.getTransportType() == TransportType.MULTIPLEX){
+ ComponentName tempCompName = SdlBroadcastReceiver.consumeQueuedRouterService();
+ if(tempCompName!=null){
+ vlad =new RouterServiceValidator(((MultiplexTransportConfig)transportConfig).getContext(),tempCompName);
+ }else{
+ vlad =new RouterServiceValidator(((MultiplexTransportConfig)transportConfig).getContext());
+ }
+ //vlad.setFlags(RouterServiceValidator.FLAG_DEBUG_VERSION_CHECK);
+ }
+ constructor(transportConfig,vlad);
+ }
+ //For unit tests
+ protected SdlConnection(BaseTransportConfig transportConfig,RouterServiceValidator rsvp){
+ constructor(transportConfig,rsvp);
+ }
+
+ private void constructor(BaseTransportConfig transportConfig,RouterServiceValidator rsvp){
_connectionListener = new InternalMsgDispatcher();
// Initialize the transport
@@ -65,10 +90,34 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
_transport = null;
}
- if (transportConfig.getTransportType() == TransportType.BLUETOOTH)
- {
- BTTransportConfig myConfig = (BTTransportConfig) transportConfig;
- _transport = new BTTransport(this, myConfig.getKeepSocketActive());
+ //Let's check if we can even do multiplexing
+ if(!isLegacyModeEnabled() &&
+ rsvp!= null &&
+ transportConfig.getTransportType() == TransportType.MULTIPLEX){
+ //rsvp = new RouterServiceValidator(((MultiplexTransportConfig)transportConfig).getContext());
+ //vlad.setFlags(RouterServiceValidator.FLAG_DEBUG_VERSION_CHECK);
+ if(rsvp.validate()){
+ Log.w(TAG, "SDL Router service is valid; attempting to connect");
+ ((MultiplexTransportConfig)transportConfig).setService(rsvp.getService());//Let thes the transport broker know which service to connect to
+ }else{
+ Log.w(TAG, "SDL Router service isn't trusted. Enabling legacy bluetooth connection.");
+ if(cachedMultiConfig == null){
+ cachedMultiConfig = (MultiplexTransportConfig) transportConfig;
+ cachedMultiConfig.setService(null);
+ }
+ enableLegacyMode(true,TransportType.BLUETOOTH); //We will use legacy bluetooth connection for this attempt
+ Log.d(TAG, "Legacy transport : " + legacyTransportRequest);
+ }
+ }
+
+ if(!isLegacyModeEnabled() && //Make sure legacy mode is not enabled
+ (transportConfig.getTransportType() == TransportType.MULTIPLEX)){
+ _transport = new MultiplexTransport((MultiplexTransportConfig)transportConfig,this);
+ }else if(isLegacyModeEnabled() && legacyTransportRequest == TransportType.BLUETOOTH){
+ Log.d(TAG, "Creating legacy bluetooth connection");
+ _transport = new BTTransport(this, true); //TODO make sure blindly sending true is ok
+ }else if(transportConfig.getTransportType() == TransportType.BLUETOOTH){
+ _transport = new BTTransport(this,((BTTransportConfig)transportConfig).getKeepSocketActive()); //FIXME we should chage this over to a special legacy config
}
else if (transportConfig.getTransportType() == TransportType.TCP)
{
@@ -98,6 +147,7 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
private void closeConnection(boolean willRecycle, byte rpcSessionID) {
synchronized(PROTOCOL_REFERENCE_LOCK) {
+
if (_protocol != null) {
// If transport is still connected, sent EndProtocolSessionMessage
if (_transport != null && _transport.getIsConnected()) {
@@ -108,7 +158,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
}
} // end-if
}
-
synchronized (TRANSPORT_REFERENCE_LOCK) {
if (willRecycle) {
if (_transport != null) {
@@ -157,12 +206,11 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
}
@Override
- public void onTransportBytesReceived(byte[] receivedBytes,
- int receivedBytesLength) {
+ public void onTransportPacketReceived(SdlPacket packet) {
// Send bytes to protocol to be interpreted
synchronized(PROTOCOL_REFERENCE_LOCK) {
if (_protocol != null) {
- _protocol.HandleReceivedBytes(receivedBytes, receivedBytesLength);
+ _protocol.handlePacketReceived(packet);
}
}
}
@@ -171,8 +219,12 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
public void onTransportConnected() {
synchronized(PROTOCOL_REFERENCE_LOCK){
if(_protocol != null){
+ boolean shouldRequestSession = _transport !=null && _transport.getTransportType()== TransportType.MULTIPLEX;
for (SdlSession s : listenerList) {
if (s.getSessionId() == 0) {
+ if(shouldRequestSession){
+ ((MultiplexTransport)_transport).requestNewSession();
+ }
startHandShake();
}
}
@@ -210,7 +262,7 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
@Override
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID) {Log.d(TAG, "onProtocolSessionStarted");
_connectionListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);
}
@@ -447,12 +499,14 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
}
}
}
- void registerSession(SdlSession registerListener) throws SdlException {
- listenerList.addIfAbsent(registerListener);
-
+ void registerSession(SdlSession registerListener) throws SdlException {
+ boolean didAdd = listenerList.addIfAbsent(registerListener);
if (!this.getIsConnected()) {
this.startTransport();
} else {
+ if(didAdd && _transport !=null && _transport.getTransportType()== TransportType.MULTIPLEX){ //If we're connected we can request the extra session now
+ ((MultiplexTransport)_transport).requestNewSession();
+ }
this.startHandShake();
}
}
@@ -463,7 +517,10 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
}
public void unregisterSession(SdlSession registerListener) {
- listenerList.remove(registerListener);
+ boolean didRemove = listenerList.remove(registerListener);
+ if(didRemove && _transport !=null && _transport.getTransportType()== TransportType.MULTIPLEX){ //If we're connected we can request the extra session now
+ ((MultiplexTransport)_transport).removeSession(registerListener.getSessionId());
+ }
closeConnection(listenerList.size() == 0, registerListener.getSessionId());
}
@@ -484,13 +541,49 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
for (SdlSession session : listenerList) {
session.onTransportDisconnected(info);
}
+ if(cachedMultiConfig!=null ){
+ if(cachedMultiConfig.getService()!=null){
+ synchronized(TRANSPORT_REFERENCE_LOCK) {
+ // Ensure transport is null
+ if (_transport != null) {
+ if (_transport.getIsConnected()) {
+ _transport.disconnect();
+ }
+ _transport = null;
+ }
+ _transport = new MultiplexTransport(cachedMultiConfig, SdlConnection.this);
+ try {
+ startTransport();
+ } catch (SdlException e) {
+ e.printStackTrace();
+ }
+ ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
+ }
+ }else{ //The service must be null or already consumed. Let's see if we can find the connection that consumed it
+ for (SdlSession session : listenerList) {
+ session.checkForOpenMultiplexConnection(SdlConnection.this);;
+ }
+
+ }
+ }
}
@Override
public void onTransportError(String info, Exception e) {
+ //If there's an error with the transport we want to make sure we clear out any reference to it held by the static list in sessions
+ SdlSession.removeConnection(SdlConnection.this);
+ //If we are erroring out to go into legacy mode, lets cache our multiplexing
+ if(isLegacyModeEnabled() && _transport!=null && TransportType.MULTIPLEX.equals(_transport.getTransportType())){
+ MultiplexTransport multi = ((MultiplexTransport)_transport);
+ cachedMultiConfig = multi.getConfig();
+ cachedMultiConfig.setService(null); //Make sure we're clearning this out
+ }else{
+ cachedMultiConfig = null; //It should now be consumed
+ }
for (SdlSession session : listenerList) {
session.onTransportError(info, e);
}
+
}
@Override
@@ -628,6 +721,79 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
mySession._incomingHeartbeatMonitor.notifyTransportActivity();
}
}
+
+ public void forceHardwareConnectEvent(TransportType type){
+ if(_transport == null){
+ Log.w(TAG, "Unable to force connect, transport was null!");
+ return;
+ }
+ if(isLegacyModeEnabled()){//We know we should no longer be in legacy mode for future connections, so lets clear out that flag
+ enableLegacyMode(false,null);
+ }
+ if(_transport!=null && (_transport.getTransportType()==TransportType.MULTIPLEX)){ //This is only valid for the multiplex connection
+ MultiplexTransport multi = ((MultiplexTransport)_transport);
+ MultiplexTransportConfig config = multi.getConfig();
+ ComponentName tempCompName = SdlBroadcastReceiver.consumeQueuedRouterService();
+ //Log.d(TAG, "Consumed component name: " +tempCompName );
+ //TODO check to see what component name connected and comapre it to what we are connected to
+ if(config.getService().equals(tempCompName)){ //If this is the same service that just connected that we are already looking at. Attempt to reconnect
+ boolean forced = multi.forceHardwareConnectEvent(TransportType.BLUETOOTH);
+
+ if(!forced && multi.isDisconnecting() ){ //If we aren't able to force a connection it means the
+ //Log.d(TAG, "Recreating our multiplexing transport");
+ _transport = new MultiplexTransport(config,this);
+ ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
+ }//else{Log.w(TAG, "Guess we're just calling it a day");}
+ }else if(tempCompName!=null){
+ //We have a conflicting service request
+ Log.w(TAG, "Conflicting services. Disconnecting from current and connecting to new");
+ Log.w(TAG, "Old service " + config.getService().toShortString());
+ Log.w(TAG, "New Serivce " + tempCompName.toString());
+ multi.disconnect();
+ config.setService(tempCompName);
+ _transport = new MultiplexTransport(config,this);
+ try {
+ startTransport();
+ } catch (SdlException e) {
+ e.printStackTrace();
+ }
+ ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
+
+ }
+ }else if(_transport.getTransportType()==TransportType.BLUETOOTH
+ && !_transport.getIsConnected()){
+ if(cachedMultiConfig!=null){
+ //We are in legacy mode, but just received a force connect. The router service should never be pointing us here if we are truely in legacy mode
+ ComponentName tempCompName = SdlBroadcastReceiver.consumeQueuedRouterService();
+ cachedMultiConfig.setService(tempCompName);
+ //We are not connected yet so we should be able to close down
+ _transport.disconnect(); //This will force us into the
+ }else{
+ Log.i(TAG, "No cached multiplexing config, transport error being called");
+ _transport.disconnect();
+ }
+ Log.w(TAG, "Using own transport, but not connected. Attempting to join multiplexing");
+ }else{
+ Log.w(TAG, "Currently in legacy mode connected to own transport service. Nothing will take place on trnasport cycle");
+ }
+ }
+
+ public static void enableLegacyMode(boolean enable, TransportType type){
+ synchronized(TRANSPORT_REFERENCE_LOCK) {
+ if(enable){
+ legacyTransportRequest = type;
+ }else{
+ legacyTransportRequest = null;
+ }
+ }
+ }
+ public static boolean isLegacyModeEnabled(){
+ synchronized(TRANSPORT_REFERENCE_LOCK) {
+ return (legacyTransportRequest!=null);
+ }
+ }
+
+
@Override
public void onProtocolSessionEndedNACKed(SessionType sessionType,